post-image

Loại bỏ các phần tử trùng trong một ArrayList như thế nào trong Java 8?

Tổng quan

Trong bài này, tôi sẽ thiệu với các bạn các cách để loại bỏ phần tử trùng trong một ArrayList với sự hỗ trợ của các tính năng mới trong Java 8.

Sử dụng phương thức distinct() trong Stream API

Phương thức distinct() trả về một Stream gồm các phần tử duy nhất, việc xác định các phần tử trùng lặp được so sánh theo theo phương thức Object.equals(Object).

Đối với ordered Stream, thứ tự sắp xếp các phần tử là ổn định (stable) : đối với các phần tử trùng lặp, phần tử xuất hiện đầu tiên trong vùng gặp phải được giữ nguyên.

Đối với các unordered Stream, không đảm bảo tính ổn định (unstable) thứ tự các phần tử.

Loại bỏ các phần tử trùng trong một ArrayList như thế nào trong Java 8?

Trong bài viết Loại bỏ các phần tử trùng trong một ArrayList , tôi đã giới thiệu với các bạn các cách để loại bỏ phần tử trùng trong một ArrayList với Java <= 7. Trong bài này, tôi sẽ giới thiệu với các bạn một số cách khác với sự hỗ trợ của các tính năng mới trong Java 8.

Tìm hiểu khoá học lập trình Java Web trong vòng 6 tháng!

Sử dụng phương thức distinct() trong Stream API

Phương thức distinct() trả về một Stream gồm các phần tử duy nhất, việc xác định các phần tử trùng lặp được so sánh theo theo phương thức Object.equals(Object).

Đối với ordered Stream, thứ tự sắp xếp các phần tử là ổn định (stable) : đối với các phần tử trùng lặp, phần tử xuất hiện đầu tiên trong vùng gặp phải được giữ nguyên.

Đối với các unordered Stream, không đảm bảo tính ổn định (unstable) thứ tự các phần tử.

Ví dụ:

package com.gpcoder.remove_duplicate;
 
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
 
public class RemoveDuplicateInArrayList1 {
 
    public static void main(String[] args) {
        List<String> listWithDuplicateElements = new ArrayList<String>();
        listWithDuplicateElements.add("JAVA");
        listWithDuplicateElements.add("J2EE");
        listWithDuplicateElements.add("JSP");
        listWithDuplicateElements.add("SERVLETS");
        listWithDuplicateElements.add("JAVA");
        listWithDuplicateElements.add("STRUTS");
        listWithDuplicateElements.add("JSP");
 
        List<String> listWithoutDuplicateElements = listWithDuplicateElements
                .stream()
                .distinct() 
                .collect(Collectors.toList());
        System.out.println(listWithoutDuplicateElements); // [JAVA, J2EE, JSP, SERVLETS, STRUTS]
    }
}

Sử dụng phương thức removeIf()

Phương thức removeIf() : chấp nhận đối số là 1 Predicate, nó loại bỏ tất cả các phần tử của Collection thỏa mãn điều kiện đã cho.

Ý tưởng cách này là lợi dụng tính năng không chứa phần tử trùng của HashSetLinkedHashSet để kiểm tra tồn tại và loại bỏ phần nó.

Ví dụ:

package com.gpcoder.remove_duplicate;
 
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
 
public class RemoveDuplicateInArrayList2 {
 
    public static void main(String[] args) {
        List<String> listWithDuplicateElements = new ArrayList<String>();
        listWithDuplicateElements.add("JAVA");
        listWithDuplicateElements.add("J2EE");
        listWithDuplicateElements.add("JSP");
        listWithDuplicateElements.add("SERVLETS");
        listWithDuplicateElements.add("JAVA");
        listWithDuplicateElements.add("STRUTS");
        listWithDuplicateElements.add("JSP");
 
        Set<String> elementsAlreadySeen = new LinkedHashSet<>();
        listWithDuplicateElements.removeIf(s -> !elementsAlreadySeen.add(s));
        System.out.println(elementsAlreadySeen); // [JAVA, J2EE, JSP, SERVLETS, STRUTS]
    }
}

Sử dụng phương thức collect() với Collectors.toCollection

Phương thức collect() chấp nhận đối số là một Collector. Trong Java 8, chúng ta có thể sử dụng phương thức Collectors.toCollection() để tạo ra Collector. Phương thức này, chấp nhận đối số là Supplier. Ý tưởng cách này cũng là lợi dụng tính năng không chứa phần tử trùng của HashSetLinkedHashSet / TreeSet.

Ví dụ bên dưới dùng để loại bỏ các sinh viên có cùng email với TreeSet.

package com.gpcoder.remove_duplicate;
 
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
 
class Student {
    private String name;
    private String email;
 
    public Student(String name, String email) {
        super();
        this.name = name;
        this.email = email;
    }
 
    public String getName() {
        return name;
    }
 
    public String getEmail() {
        return email;
    }
 
    @Override
    public String toString() {
        return "Student [name=" + name + ", email=" + email + "]";
    }
}
 
public class RemoveDuplicateInArrayList3 {
 
    public static void main(String[] args) {
        List<Student> studentsWithtDuplicate = new ArrayList<>();
        studentsWithtDuplicate.add(new Student("Nguyen Nhat", "nguyennhat@gmail.com"));
        studentsWithtDuplicate.add(new Student("Le Van", "levan@gmail.com"));
        studentsWithtDuplicate.add(new Student("Tran Khoa", "trankhoa@gmail.com"));
        studentsWithtDuplicate.add(new Student("Le Vo", "levan@gmail.com"));
        studentsWithtDuplicate.add(new Student("Ly Nguyen", "lynguyen@gmail.com"));
 
        Set<Student> studentsWithoutDuplicate = studentsWithtDuplicate.stream()
                .collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getEmail))));
        studentsWithoutDuplicate.forEach(s -> System.out.println(s));
    }
}

Output của chương trình:

Student [name=Le Van, email=levan@gmail.com]
Student [name=Ly Nguyen, email=lynguyen@gmail.com]
Student [name=Nguyen Nhat, email=nguyennhat@gmail.com]
Student [name=Tran Khoa, email=trankhoa@gmail.com]

Trong thực tế, người ta thường sử dụng phương thức distinct() để loại phần tử trùng. Sử dụng removeIf() hay collect() không tốt về performance so với distinct() và nó trả về một Set thay vì List như mong muốn, cần phải chuyển Set sang List. Tuy nhiên trong một số trường hợp chúng ta cũng có thể sử dụng cách này, nên tôi cũng giới thiệu với các bạn để thêm lựa chọn khi sử dụng.

Nguồn: https://gpcoder.com/4450-loai-bo-cac-phan-tu-trung-trong-mot-arraylist-nhu-the-nao-trong-java-8/


Hãy tham gia nhóm Học lập trình để thảo luận thêm về các vấn đề cùng quan tâm.

Leave a Reply

Your email address will not be published. Required fields are marked *