Tôi có một ArrayList
với một số bản ghi và một cột chứa tên khí là CO2 CH4 SO2, v.v. Bây giờ tôi chỉ muốn truy xuất các tên khí khác nhau (duy nhất) mà không cần đặt lại từ ArrayList
. Nó được hoàn thiện bằng cách nào?
Tôi có một ArrayList
với một số bản ghi và một cột chứa tên khí là CO2 CH4 SO2, v.v. Bây giờ tôi chỉ muốn truy xuất các tên khí khác nhau (duy nhất) mà không cần đặt lại từ ArrayList
. Nó được hoàn thiện bằng cách nào?
Câu trả lời:
Bạn nên sử dụng a Set
. A Set
là một Bộ sưu tập không chứa trùng lặp.
Nếu bạn có một List
chứa các bản sao, bạn có thể nhận được các mục nhập duy nhất như sau:
List<String> gasList = // create list with duplicates...
Set<String> uniqueGas = new HashSet<String>(gasList);
System.out.println("Unique gas count: " + uniqueGas.size());
LƯU Ý : Hàm HashSet
tạo này xác định các bản sao bằng cách gọi phương thức equals () của các phần tử .
java: no suitable constructor found for HashSet
. Bất kỳ ý tưởng tại sao điều này xảy ra?
Phương thức khác biệt là một hoạt động trung gian lọc luồng và chỉ cho phép các giá trị khác biệt (theo mặc định sử dụng phương thức Đối tượng :: bằng) để chuyển cho hoạt động tiếp theo.
Tôi đã viết một ví dụ bên dưới cho trường hợp của bạn,
// Create the list with duplicates.
List<String> listAll = Arrays.asList("CO2", "CH4", "SO2", "CO2", "CH4", "SO2", "CO2", "CH4", "SO2");
// Create a list with the distinct elements using stream.
List<String> listDistinct = listAll.stream().distinct().collect(Collectors.toList());
// Display them to terminal using stream::collect with a build in Collector.
String collectAll = listAll.stream().collect(Collectors.joining(", "));
System.out.println(collectAll); //=> CO2, CH4, SO2, CO2, CH4 etc..
String collectDistinct = listDistinct.stream().collect(Collectors.joining(", "));
System.out.println(collectDistinct); //=> CO2, CH4, SO2
Tôi hy vọng tôi hiểu đúng câu hỏi của bạn: giả sử rằng các giá trị thuộc loại String
, cách hiệu quả nhất có lẽ là chuyển đổi thành a HashSet
và lặp lại nó:
ArrayList<String> values = ... //Your values
HashSet<String> uniqueValues = new HashSet<>(values);
for (String value : uniqueValues) {
... //Do something
}
ArrayList values = ... // your values
Set uniqueValues = new HashSet(values); //now unique
Đây là cách đơn giản mà không cần dùng đến trình so sánh tùy chỉnh hoặc những thứ tương tự:
Set<String> gasNames = new HashSet<String>();
List<YourRecord> records = ...;
for(YourRecord record : records) {
gasNames.add(record.getGasName());
}
// now gasNames is a set of unique gas names, which you could operate on:
List<String> sortedGasses = new ArrayList<String>(gasNames);
Collections.sort(sortedGasses);
Lưu ý: Việc sử dụng TreeSet
thay vì HashSet
sẽ cung cấp danh sách mảng được sắp xếp trực tiếp và ở trên Collections.sort
có thể bị bỏ qua, nhưng TreeSet
nếu không thì ít hiệu quả hơn, vì vậy nó thường tốt hơn và hiếm khi tệ hơn, để sử dụng HashSet
ngay cả khi cần sắp xếp.
Khi thực hiện cùng một truy vấn, tôi đã gặp khó khăn trong việc điều chỉnh các giải pháp cho trường hợp của mình, mặc dù tất cả các câu trả lời trước đó đều có thông tin chi tiết tốt.
Đây là một giải pháp khi người ta phải lấy một danh sách các đối tượng duy nhất, KHÔNG phải chuỗi. Giả sử, một danh sách các đối tượng Record. Record
lớp chỉ có thuộc tính của kiểu String
, KHÔNG có thuộc tính của kiểu int
. Ở đây việc triển khai hashCode()
trở nên khó khăn vì hashCode()
cần phải trả về một int
.
Sau đây là một Record
Class mẫu .
public class Record{
String employeeName;
String employeeGroup;
Record(String name, String group){
employeeName= name;
employeeGroup = group;
}
public String getEmployeeName(){
return employeeName;
}
public String getEmployeeGroup(){
return employeeGroup;
}
@Override
public boolean equals(Object o){
if(o instanceof Record){
if (((Record) o).employeeGroup.equals(employeeGroup) &&
((Record) o).employeeName.equals(employeeName)){
return true;
}
}
return false;
}
@Override
public int hashCode() { //this should return a unique code
int hash = 3; //this could be anything, but I would chose a prime(e.g. 5, 7, 11 )
//again, the multiplier could be anything like 59,79,89, any prime
hash = 89 * hash + Objects.hashCode(this.employeeGroup);
return hash;
}
Như đã đề xuất trước đó bởi những người khác, lớp cần ghi đè cả phương thức equals()
và hashCode()
phương thức để có thể sử dụng HashSet
.
Bây giờ, giả sử, danh sách Bản ghi là allRecord
( List<Record> allRecord
).
Set<Record> distinctRecords = new HashSet<>();
for(Record rc: allRecord){
distinctRecords.add(rc);
}
Điều này sẽ chỉ thêm các Bản ghi riêng biệt vào Hashset, differenceRecords.
Hi vọng điêu nay co ich.
Nếu bạn có một mảng của một số loại đối tượng (bean), bạn có thể thực hiện điều này:
List<aBean> gasList = createDuplicateGasBeans();
Set<aBean> uniqueGas = new HashSet<aBean>(gasList);
như Mathias Schwarz đã nói ở trên, nhưng bạn phải cung cấp cho aBean của mình các phương thức hashCode()
và equals(Object obj)
điều đó có thể được thực hiện dễ dàng trong Eclipse bằng menu chuyên dụng ' Generate hashCode() and equals()
' (khi ở trong bean Class). Set sẽ đánh giá các phương thức được ghi đè để phân biệt các đối tượng bằng nhau.