如何在 Java 中过滤不同的元素

仅过滤 Collection 中的唯一元素

扫码关注《Java学研大本营》,加入读者群,分享更多精彩

介绍

  • 当我们从一台机器到另一台机器交换数据时,重复条目是非常常见的问题。

  • 作为客户端,在使用这些记录时,我们必须实现一个逻辑来处理这些重复记录。

  • 在本博客中,我们将了解如何在 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 列表。我们可以通过打印来检查。

  • 如我们所见,我们重复的 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));
  • 现在我们可以通过打印我们不同的电子邮件列表来进行测试。

  • 到目前为止,我们一直在过滤 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 不适用于自定义类型?

  • 造成这种情况的主要原因不是 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 方法将起作用。

  • 我们可以看到过滤掉重复值的结果。

哈希集

  • 我们还可以使用我们用于原始过滤的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 中从元素列表中过滤出唯一元素的各种方法。

  • 我们讨论了使用 Hashset 和流 api 来实现它。

参考文章: https://medium.com/javarevisited/how-to-filter-distinct-elements-in-java-477ed0e3d27b

推荐书单

1.《项目驱动零起点学Java》

购买链接:https://item.jd.com/13607758.html

《项目驱动零起点学Java》贯穿6个完整项目,经过作者多年教学经验提炼而得,项目从小到大、从短到长,可以让读者在练习项目的过程中,快速掌握一系列知识点。

作者是国内知名Java教学者和传播者,一路披荆斩棘,兢兢业业20余年。积累了丰富的“培”“训”经验,也产出了很多优质的教学理论。

Java语言经过数十年的发展,体系逐渐变得庞大而复杂,本书芟繁就简,提炼出了最为重要的知识点,可以让读者轻松上手。本书配套有专栏课程,课程中提供了扩展内容。

《项目驱动零起点学Java》共分 13 章,围绕 6 个项目和 258 个代码示例,分别介绍了走进Java 的世界、变量与数据类型、运算符、流程控制、方法、数组、面向对象、异常、常用类、集合、I/O流、多线程、网络编程相关内容。《项目驱动零起点学Java》总结了马士兵老师从事Java培训十余年来经受了市场检验的教研成果,通过6 个项目以及每章的示例和习题,可以帮助读者快速掌握Java 编程的语法以及算法实现。扫描每章提供的二维码可观看相应章节内容的视频讲解。

2.《Java编程讲义》

购买链接:https://item.jd.com/13495830.html

《Java编程讲义》根据目前Java开发领域的实际需求,从初学者角度出发,详细讲解了Java技术的基础知识。

全书共15章,包括Java开发入门,Java语言基础,Java控制结构,数组,面向对象编程,继承和多态,抽象类、接口和内部类,异常处理,Java常用类库,集合与泛型,Lambda表达式,输入-输出流,多线程,JDBC数据库技术,网络编程等内容。内容全面覆盖.1ava开发必备的基础知识点,结合生活化案例展开讲解,程序代码给出了详细的注释,能够使初学者轻松领会Java技术精髓,快速掌握Java开发技能。

《Java编程讲义》适合作为高等院校相关专业的教材及教学参考书,也适合作为Java开发入门者的自学用书,还可供开发人员查阅、参考。

精彩回顾

想要代码干净又整洁?这里有十大原则

通过自学成为开发者的 9 种方法

怎么做一个有产品意识的软件工程师?

扫码关注《Java学研大本营》,加入读者群,分享更多精彩

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值