2012-03-05 49 views
16

Tôi mới sử dụng java, tôi muốn lưu trữ một loạt các cặp đôi. Mã của tôi trông giống như sau:Làm thế nào để lưu trữ một mảng các cặp trong java?

import java.util.ArrayList; 
import java.util.Map.Entry; 

List<Entry<Double, Double>> values = new ArrayList<>(); 
Entry<Double, Double> pair; 
// set pair values: 
// pair.setKey(0.5); // this method does not exists 
// pair.setValue(3.6); 
values.add(pair); 

Làm cách nào để khởi tạo biến ghép nối? Có cấu trúc nào tốt hơn để lưu trữ mảng cặp đôi của tôi không?

+1

Nếu bạn không thể bị làm phiền, bạn luôn có thể thử: http://www.javatuples.org/ – Nim

+0

Bản sao của http://stackoverflow.com/questions/521171/a-java-collection-of-value-pairs -tuples –

Trả lời

15

Tạo lớp của riêng bạn để đại diện cho một cặp và thêm một constructor mà hai đối số:

public class MyPair 
{ 
    private final Double key; 
    private final Double value; 

    public MyPair(Double aKey, Double aValue) 
    { 
     key = aKey; 
     value = aValue; 
    } 

    public Double key() { return key; } 
    public Double value() { return value; } 
} 

Xem câu trả lời này vì những lý do tại sao một Pair không tồn tại trong Java: What is the equivalent of the C++ Pair<L,R> in Java?

+2

Tôi ngạc nhiên rằng không có cái gì mà tôi có thể sử dụng trong thư viện java chuẩn cho một điều đơn giản như vậy –

+4

Xem câu trả lời này vì lý do tại sao không có 'Cặp' như vậy: http://stackoverflow.com/questions/156275/ what-is-the-equivalent-of-the-c-pairl-r-trong-java – hmjd

+0

lưu ý rằng giải pháp này làm tăng sự phức tạp của dự án rất nhiều khi bạn có thể có 100 lớp khác nhau có hiệu quả các cặp, nhưng mỗi loại có loại riêng biệt; yêu cầu marshalling tùy chỉnh giữa các loại, đó là cả hai dễ bị lỗi, trông xấu xí, và đắt tiền (như bạn không thể blit từ một đến khác, và sự lưu trữ cache). Ok nếu tất cả các cặp đôi đều thực hiện các marshallers của riêng mình, điều này giải quyết mọi vấn đề ngoại trừ hiệu suất và các phiên bản khác nhau của cặp có giao diện cơ sở khác nhau, có thể được giải quyết bằng cách không có giao diện và sử dụng sự phản chiếu, nhưng bây giờ bạn có vấn đề khác. – Dmitry

1

Bạn có thể sử dụng một bản đồ để giải quyết vấn đề này.

+1

đúng nếu mỗi "khóa" là duy nhất. 'Bản đồ' không cho phép các phím trùng lặp – amit

+0

Hai cặp có thể có cùng số bên trái, ví dụ: [(2, 6.3), (2, 8.4)] –

+0

Nếu bạn có một' Double' làm khóa, bạn phải xem http://stackoverflow.com/q/1074781/1065197 –

1

Có phải Entry một lớp học bạn đã xác định không? Bạn khởi tạo nó với new.

Entry<Double, Double> pair = new Entry<Double, Double>(d1, d2); 

Note Tôi giả sử bạn định nghĩa một constructor mà mất 2 đôi, và bạn có tài liệu tham khảo cho d1d2.

Tôi đề nghị bạn KHÔNG sử dụng lớp Map.Entry. Các ngữ nghĩa cho lớp đó là các giá trị là một khóa và một giá trị, phù hợp với cách thức hoạt động của Maps.

+0

xem xét hàng nhập: "import java.util.Map.Entry;" – rompetroll

0

Nếu bạn có quyền truy cập vào lớp nhập, bạn có thể tạo một hàm tạo lấy khóa và giá trị làm tham số.

Entry<Double, Double> pair = new Entry<Double, Double>(0.5, 3.6); 
values.add(pair); 
+0

Tôi nhận được lỗi sau: 'Không thể khởi tạo kiểu Map.Entry ' –

0

Loại Map.Entry mà bạn đang cố gắng sử dụng chỉ là giao diện và do đó không thể được khởi tạo. Nếu bạn muốn (sử dụng sai) sử dụng các loại nội bộ Map, thì việc triển khai Map.Entry cụ thể HashEntry sẽ là một tùy chọn.

Tuy nhiên, tốt hơn hết là nên triển khai bạn sở hữu loại Ghép đôi. Hoặc sử dụng Bản đồ thay vì một mảng nếu phù hợp với nhu cầu của bạn.

5

Bạn không muốn sử dụng Mục nhập là giao diện, không phải là CLASS. Giao diện đó được sử dụng bởi việc triển khai Set khi bạn gọi đến mục nhậpSet() trên một lớp thực hiện Bản đồ. Về cơ bản nó cho phép bạn thao tác với Map được thực hiện như thể nó là một Set.

Bạn sẽ làm gì (nhưng không thể) là điều này. Nếu bạn cố gắng làm điều này bạn sẽ thấy một lỗi trình biên dịch dọc theo dòng "Không thể khởi tạo kiểu Map.Entry". Đó là vì Map.Entry là một giao diện chứ không phải là một lớp. Một giao diện không chứa bất kỳ mã thực nào, do đó không có hàm tạo thực nào để chạy ở đây.

Entry<Double, Double> pair = new Entry<Double, Double>(); 

Nếu bạn nhìn vào các tài liệu bên dưới, bạn có thể thấy rõ ràng ở trên cùng rằng đó là "Giao diện bản đồ.Entry" có nghĩa là giao diện. http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Map.Entry.html

Bạn nên làm gì thay vì cố gắng khởi tạo giao diện, điều không thể, là tạo lớp của riêng bạn gọi là Ghép nối. Một cái gì đó như thế này. Hãy nhớ thay đổi gói nếu bạn sử dụng mã bên dưới.

package org.mike.test; 

public class Pair { 
    private double x = 0.0; 
    private double y = 0.0; 

    public Pair(double x, double y) 
    { 
     this.x = x; 
     this.y = y; 
    } 

    public Pair() 
    { 

    } 

    public double getX() { 
     return x; 
    } 

    public void setX(double x) { 
     this.x = x; 
    } 

    public double getY() { 
     return y; 
    } 

    public void setY(double y) { 
     this.y = y; 
    } 


} 

Sau khi viết lớp Pair, mã của bạn giờ sẽ trông như thế này.

package org.mike.test; 

import java.util.ArrayList; 
import org.mike.test.Pair; //You don't need this if the Pair class is in the same package as the class using it 

public class tester { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     ArrayList<Pair> values = new ArrayList<Pair>(); 
     Pair pair = new Pair(); 
     // set pair values: 
     pair.setY(3.6); 
     pair.setX(3.6); 
     values.add(pair); 
    } 

} 
+0

Tốt đẹp, và cho rằng bạn đã cho chúng ta một Pair (double, double) constructor, tôi sẽ đơn giản hóa và loại bỏ setX/Y () các cuộc gọi và sử dụng Pair pair = new Pair (3.6, 3.6); – Leif

0

Một cách tiếp cận, và có lẽ là cách hiệu quả nhất để lưu trữ và mảng của các cặp đôi là sử dụng một mảng duy nhất của đôi, và sử dụng (2 * i) và (2 * i + 1) như lập chỉ mục của bạn kế hoạch. Ngoài ra, bạn có được lợi thế là mảng sẽ được khởi tạo cho tất cả 0 khi bạn tạo nó, không yêu cầu thêm bước nào. Thật không may có thêm một chút chi phí mã hóa để thực hiện add() và remove(), nhưng đáng ngạc nhiên, nó có lẽ ít hơn việc tạo lớp container của riêng bạn cho cặp.

class MyClass { 
    double[] values; 
    int count; 

    MyClass(int initialCapacity) { 
     values = new double[initialCapacity*2]; 
    } 

    // adding a pair 
    void addPair(double x, double y) { 
     if (count*2 >= values.length) { 
      values = Arrays.copyOf(values, values.length*2); 
     } 
     values[count*2] = x; 
     values[count*2 + 1] = y; 
     count++; 
    } 

    void remove(int index) { 
     if (index >= count) throw new IndexOutOfBoundsException(); 

     if (index < --count) { 
      System.arraycopy(values, (index+1)*2, values, index*2, (count - index) * 2); 
     } 
    } 

    int size() { return count; } 

    // both these should check that index < count. 
    double getX(int index) { return values[index*2]; } 
    double getY(int index) { return values[index*2 + 1]; } 

    void exampleIteration() { 
     // getX/Y accessors are examples of how to get 
     // the values, but it will be more efficient 
     // in most cases to just access the array 
     // array directly as so... 
     for (int i=0 ; i<count ; ++i) { 
      System.out.printf("%d: (%f,%f)%n", i, values[i*2], values[i*2+1]); 
     } 
    } 
} 
2

Không thể bạn chỉ cần sử dụng

public class MyClass<A,B> extends ArrayList{ 
private A first; 
private B second; 
public MyClass(A first, B second){ 
super(); 
this.first = first; 
this.second = second;} 
} 

và sau đó thêm một số hình thức của phương pháp thêm, cùng với một phương pháp mutator đầu tiên và thứ hai accessor &? Tôi sắp xếp mới để lập trình, nhưng cách này có vẻ như có thể hoạt động và có thể truy cập được vào những thứ khác ngoài DOUBLE, (trong trường hợp bạn muốn sử dụng các loại khác như Integer hoặc String) .

Các vấn đề liên quan