2009-06-12 44 views
8

Tôi có một ArrayList trong Java được tạo thành từ một loại có chứa hai chuỗi và một số nguyên. Tôi có thể kiểm tra thành công nếu một phần tử của ArrayList này bằng một phần tử khác nhưng tôi thấy rằng phương thức chứa không thành công. Tôi tin rằng điều này là do thực tế là loại của tôi không phải là nguyên thủy.Cách tốt nhất để sử dụng có chứa trong một ArrayList trong Java là gì?

Bây giờ tôi thấy hai lựa chọn thay thế này và tôi tự hỏi đó là lựa chọn tốt nhất:

  1. Để thực hiện của riêng tôi chứa phương pháp bằng cách duyệt qua ArrayList và thử nghiệm sự bình đẳng của mỗi yếu tố chống lại một Tôi tìm kiếm và sau đó phá vỡ vòng lặp.

  2. Hoặc sử dụng HashMap của loại của tôi làm khóa với số nguyên làm giá trị thay vì ArrayList. Ở đây tôi có thể sử dụng phương thức containsKey để kiểm tra xem một phần tử đã tồn tại trong HashMap chưa.

Cách báo trước duy nhất với phương pháp số 2 là giá trị phần lớn là thừa trong trường hợp của tôi.

+1

Nhìn vào mã nguồn cho ArrayList và bạn sẽ thấy rằng việc triển khai khá đơn giản. – iny

Trả lời

24

Rất có thể, bạn chỉ đơn giản là quên ghi đè equals()hashCode() trong loại của bạn. equals() là séc .

Từ Javadoc:

Returns true nếu danh sách này bao gồm các yếu tố cụ thể. Chính thức hơn, trả về true nếu và chỉ khi danh sách này chứa ít nhất một phần tử e sao cho (o==null ? e==null : o.equals(e)).

Kể từ khi triển khai mặc định equals kiểm tra tính bình đẳng tham chiếu, nó không thích hợp cho các loại dữ liệu tùy chỉnh như thế này.

(. Và nếu bạn không ghi đè equalshashCode, sử dụng các loại của bạn là chìa khóa trong một HashMap sẽ không kém vô ích)


Edit: Lưu ý rằng để ghi đè, bạn phải cung cấp chính xác chữ ký.

class MyDataType { 
    public boolean equals(MyDataType other) { // WRONG! 
     ... 
    } 
    public boolean equals(Object other) { // Right! 
     ... 
    } 
} 

Đây là một đối số rất mạnh để sử dụng chú thích @Override; ví dụ đầu tiên sẽ thất bại trong thời gian biên dịch nếu được chú thích bằng @Override.

+0

Trong lớp tôi đã chỉ định phương thức bằng: boolean bằng nhau (HierarchicalTreemapElement hte) { if ((this.getChild(). Equals (hte.getChild()) && (this.getParent(). Bằng (hte.getParent()) && (this.getQuantity() == (hte.getQuantity()))))) { trả về true; } người khác { trả về false; } } Nhưng vẫn bị lỗi nếu danh sách mảng được sử dụng. Tôi cần làm gì cho hashCode? –

+3

Bạn đã ghi đè bằng() không chính xác, như Jon Skeet nói. Đặt chú thích @Override trước chữ ký phương thức chỉ để chắc chắn (nếu nó không chính xác, nó sẽ tạo ra một lỗi biên dịch). –

+1

Đối với hashCode, nếu bạn đã ghi đè nó, nó có thể là đủ. Nếu bạn không có, bạn chắc chắn nên; ghi đè bằng() nên * luôn luôn * ngụ ý ghi đè hashCode(). –

3

Bạn đã ghi đè phương thức bằng? Điều này là cần thiết để làm cho chứa hoạt động chính xác.

0

có thể sử dụng lớp Integer để thay thế? sau đó bạn có thể so sánh đối tượng

14

Đoán của tôi là bạn chỉ viết phương thức bằng "được nhập mạnh mẽ" thay vì ghi đè bằng (Đối tượng).Nói cách khác, nếu bạn đã có:

public boolean equals(Foo f) 

bạn cần

public boolean equals(Object o) 

cũng như để ghi đè Object.equals.

Điều đó sẽ phù hợp với "bằng các công trình nhưng chứa không vì xét nghiệm của bạn có thể gọi equals mạnh mẽ, đánh máy, nhưng ArrayList thì không.

+0

Để mở rộng trên nhận xét 'vượt qua bài kiểm tra nhưng không thành công', hãy lưu ý rằng nếu bạn đang thử nghiệm MyClass # equals, bạn nên làm điều đó bằng cách sử dụng các cuộc gọi đối với Object # bằng, đi qua một đối tượng. (Làm một lưu ý để đi sửa chữa bài kiểm tra đơn vị của mình, khi anh nghĩ rằng anh ta không làm điều này đúng). –

+0

Hmm ... Tôi không chắc câu trả lời của tôi có thực sự thêm bất cứ điều gì vào câu trả lời của các luật sư không. Tetsujin no Oni: bạn có muốn sao chép bình luận của bạn về câu trả lời đó, và sau đó tôi có thể xóa câu trả lời này không? –

2

Hãy nhớ rằng nếu bạn không ghi đè lên equals() phương pháp , thì hai đối tượng thuộc loại của bạn chỉ bằng nhau nếu chúng là cùng một thể hiện của đối tượng đó. Lớp ArrayList sử dụng phương pháp này để kiểm tra xem nó có chứa đối tượng đã cho hay không. nó phải có một đối tượng như một tham số và không phải là một tham số và không phải là một thông số. e bằng(). Nếu bạn không làm điều này, thì HashMap hoặc HashSet sẽ không xác định hai đối tượng của bạn là bằng nhau, ngay cả khi ArrayList thực hiện (HashMap kiểm tra các hash giống nhau và sau đó gọi equals() trên chúng để kiểm tra sự bình đẳng thực tế). Vì vậy, nếu ArrayList nói rằng hai mục không bằng nhau, thì không có cách nào mà HashMap sẽ là một trong hai. Điều này có nghĩa là giải pháp thứ hai của bạn không hoạt động.

Đề xuất của tôi là kiểm tra xem bạn có thực sự ghi đè bằng() và hashCode() đúng không và chữ ký của chúng khớp với chữ cái trong lớp Object.

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