仅过滤 Collection 中的唯一元素

java list过滤获取一个 java过滤集合里的元素_java list过滤获取一个

介绍

  • 当我们从一台机器到另一台机器交换数据时,重复条目是非常常见的问题。
  • 作为客户端,在使用这些记录时,我们必须实现一个逻辑来处理这些重复记录。
  • 在本博客中,我们将了解如何在 Java 中处理重复项。

用例

  • 我们将以我们提供的客户列表和 emailId 为例。我们的主要目标是从中过滤掉不同的记录。
// list of emailId
List<String> emailList = List.of("abc@gmail.com", "pqr@gmail.com", "tuf@gmail.com", "lth@gmail.com", "abc@gmail.com");

// list of emailId
List<Customer> customers = List.of(new Customer(1, 23,"abc@gmail.com"),new Customer(2, 25,"xbc@gmail.com"),new Customer(1, 23,"abc@gmail.com"));

使用哈希集

  • 首先我们将使用Hashset 数据结构。如果你不知道,hashset 只包含唯一元素,如果你尝试添加两次相同的元素,hashset 将返回 false。
  • 所以我们保证在 hashset 中有唯一的元素。
  • 在下面的示例中,我们正在迭代每个 emailId 并添加到我们的集合中。 完成后,我们从这个集合中创建一个不同的列表。
List<String> emailList = List.of("abc@gmail.com", "pqr@gmail.com", "tuf@gmail.com", "lth@gmail.com", "abc@gmail.com");
        emailList.stream().forEach(a-> System.out.println(a));

        System.out.println("==========================");

        // using hashset
        HashSet<String> set = new HashSet<>();
        for ( String emailId: emailList ) {
            set.add(emailId);
        }
        emailList = new ArrayList<>(set);
        emailList.stream().forEach(a-> System.out.println(a));
  • 现在我们有了唯一的 emailId 列表。我们可以通过打印来检查。

java list过滤获取一个 java过滤集合里的元素_java_02

  • 如我们所见,我们重复的 emailId 已从原始电子邮件列表中过滤掉。

使用不同的方法

  • 我们可以使用的其他方法是来自Streams API 的 in-build distinct() 方法。(https://medium.com/javarevisited/7-best-java-tutorials-and-books-to-learn-lambda-expression-and-stream-api-and-other-features-3083e6038e14?source=---------14------------------)
  • 让我们从列表创建 Stream并执行 distinct() 操作以仅过滤掉唯一元素。(https://javarevisited.blogspot.com/2014/03/2-examples-of-streams-with-Java8-collections.html)
List<String> emailList = List.of("abc@gmail.com", "pqr@gmail.com", "tuf@gmail.com", "lth@gmail.com", "abc@gmail.com");
        emailList.stream().forEach(a-> System.out.println(a));

        System.out.println("==========================");
        
        // streams api
        List<String> distinctEmailList = emailList.stream().distinct().collect(Collectors.toList());
        distinctEmailList.stream().forEach(a-> System.out.println(a));
  • 现在我们可以通过打印我们不同的电子邮件列表来进行测试。

java list过滤获取一个 java过滤集合里的元素_jvm_03

  • 到目前为止,我们一直在过滤 Primitive 类型,但接下来我们将使用自定义对象类型,我们将删除重复的对象。

客户 POJO

  • 让我们首先创建自定义类 Customer,它只是 POJO。
import java.util.Objects;

public class Customer {

    private int id;
    private int age;
    private String emailId;

    public Customer(int id, int age, String emailId) {
        this.id = id;
        this.age = age;
        this.emailId = emailId;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getEmailId() {
        return emailId;
    }

    public void setEmailId(String emailId) {
        this.emailId = emailId;
    }

    @Override
    public String toString() {
        return "Customer{" +
  • 现在让我们通过创建客户对象来创建示例客户列表。
  • 现在避免使用 api流 distinct() 方法并检查它是否也在对象上工作。
List<Customer> customers = List.of(new Customer(1, 23,"abc@gmail.com"),
                new Customer(2, 25,"xbc@gmail.com"),
                new Customer(1, 23,"abc@gmail.com"));

        customers.stream().forEach(a-> System.out.println(a));

        System.out.println("==========================");

        customers.stream().distinct().forEach(a-> System.out.println(a));
  • 但是当我们 print 时,我们发现它不是真的。它仍然打印重复的客户。
  • 这意味着 distinct 不适用于自定义类型?

java list过滤获取一个 java过滤集合里的元素_Java_04

  • 造成这种情况的主要原因不是 distinct() 方法的问题,而是hashcode 和 equals 方法的问题。(https://javarevisited.blogspot.com/2013/08/10-equals-and-hashcode-interview.html)
  • 我们必须在我们之前创建的Customer POJO 中覆盖equals方法和hashcode方法。
  • 正如我们所看到的,我们正在比较客户类的每个属性,在hashcode中,我们使用客户类属性来计算 hashcode 。(https://javarevisited.blogspot.com/2011/02/how-to-write-equals-method-in-java.html)
@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Customer customer = (Customer) o;
        return id == customer.id && age == customer.age && emailId.equals(customer.emailId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, age, emailId);
    }
  • 一旦我们添加了 hashCode 和 equals 方法,那么我们在流上的 distinct 方法将起作用。
  • 我们可以看到过滤掉重复值的结果。

java list过滤获取一个 java过滤集合里的元素_servlet_05

哈希集

  • 我们还可以使用我们用于原始过滤的HashSet 。(https://www.java67.com/2014/01/when-to-use-linkedhashset-vs-treeset-vs-hashset-java.html)
HashSet<Customer> set = new HashSet<>();
        customers.stream().forEach(a->set.add(a));

        ArrayList<Customer> distinctCustomers = new ArrayList<>(set);
        distinctCustomers.stream().forEach(a-> System.out.println(a));
  • 这是结果。

java list过滤获取一个 java过滤集合里的元素_java list过滤获取一个_06

结论

  • 在这篇博客中,我们看到了 Java 中从元素列表中过滤出唯一元素的各种方法。
  • 我们讨论了使用 Hashset 和流 api 来实现它。