Nhận các giá trị duy nhất từ ​​danh sách mảng trong java


81

Tôi có một ArrayListvớ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?


4
Tôi sẽ cập nhật các thẻ. Đây là một câu hỏi Java và tôi tin rằng nó không liên quan đến JSF và primefaces ...
Mathias Schwarz

Câu trả lời:


133

Bạn nên sử dụng a Set. A Setlà một Bộ sưu tập không chứa trùng lặp.

Nếu bạn có một Listchứ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 HashSettạ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ử .


điều đó ngụ ý rằng 2 bản ghi được coi là bằng nhau (theo nghĩa của HashSet) nếu tên của chúng bằng nhau.
njzk2

@ njzk2 - I figured đó sẽ là khá rõ ràng, nhưng tôi đoán tôi có thể chỉnh sửa để trỏ nó ra một cách rõ ràng ...
jahroy

Tôi nhận được một lỗi khi cố gắng thực hiện các mã trên: java: no suitable constructor found for HashSet. Bất kỳ ý tưởng tại sao điều này xảy ra?
Lordlabakdas

66

Bạn có thể sử dụng Java 8 Stream API .

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

11

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 HashSetvà lặp lại nó:

ArrayList<String> values = ... //Your values
HashSet<String> uniqueValues = new HashSet<>(values);
for (String value : uniqueValues) {
   ... //Do something
}

6
ArrayList values = ... // your values
Set uniqueValues = new HashSet(values); //now unique

Bây giờ tôi đang lấy các phần tử duy nhất từ ​​danh sách nhưng nó đang được sắp xếp bởi chính nó, nhưng tôi cần dữ liệu không được sắp xếp theo thứ tự. Làm thế nào nó có thể được thực hiện?
SDas

6

Đâ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 TreeSetthay vì HashSetsẽ cung cấp danh sách mảng được sắp xếp trực tiếp và ở trên Collections.sortcó thể bị bỏ qua, nhưng TreeSetnế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 HashSetngay cả khi cần sắp xếp.


3

bạn có thể sử dụng nó để tạo một danh sách Duy nhất

ArrayList<String> listWithDuplicateValues = new ArrayList<>();
list.add("first");
list.add("first");
list.add("second");

ArrayList uniqueList = (ArrayList) listWithDuplicateValues.stream().distinct().collect(Collectors.toList());

2

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. Recordlớ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 RecordClass 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()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.


1

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()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.


1
  @SuppressWarnings({ "unchecked", "rawtypes" })
    public static List getUniqueValues(List input) {
    return new ArrayList<>(new HashSet<>(input));
    }

đừng quên triển khai phương pháp bằng của bạn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.