• 面试:List 如何根据对象的属性去重?


    一、去除List中重复的String

    1. public List<String> removeStringListDupli(List<String> stringList) {
    2.     Set<Stringset = new LinkedHashSet<>();
    3.     set.addAll(stringList);
    4.     stringList.clear();
    5.     stringList.addAll(set);
    6.     return stringList;
    7. }

    或使用Java8的写法:

    List<String> unique = list.stream().distinct().collect(Collectors.toList());
    

    二、List中对象去重

    比如现在有一个 Person类:

    1. public class Person {
    2.     private Long id;
    3.     private String name;
    4.     public Person(Long id, String name) {
    5.         this.id = id;
    6.         this.name = name;
    7.     }
    8.     public Long getId() {
    9.         return id;
    10.     }
    11.     public void setId(Long id) {
    12.         this.id = id;
    13.     }
    14.     public String getName() {
    15.         return name;
    16.     }
    17.     public void setName(String name) {
    18.         this.name = name;
    19.     }
    20.     @Override
    21.     public String toString() {
    22.         return "Person{" +
    23.                 "id=" + id +
    24.                 ", name='" + name + '\'' +
    25.                 '}';
    26.     }
    27. }

    重写Person对象的equals()方法和hashCode()方法:

    1.  @Override
    2. public boolean equals(Object o) {
    3.     if (this == o) return true;
    4.     if (o == null || getClass() != o.getClass()) return false;
    5.     Person person = (Person) o;
    6.     if (!id.equals(person.id)) return false;
    7.     return name.equals(person.name);
    8. }
    9. @Override
    10. public int hashCode() {
    11.     int result = id.hashCode();
    12.     result = 31 * result + name.hashCode();
    13.     return result;
    14. }

    下面对象去重的代码:

    1. Person p1 = new Person(1l"jack");
    2. Person p2 = new Person(3l"jack chou");
    3. Person p3 = new Person(2l"tom");
    4. Person p4 = new Person(4l"hanson");
    5. Person p5 = new Person(5l"胶布虫");
    6. List<Person> persons = Arrays.asList(p1, p2, p3, p4, p5, p5, p1, p2, p2);
    7. List<Person> personList = new ArrayList<>();
    8. // 去重
    9. persons.stream().forEach(
    10.     p -> {
    11.         if (!personList.contains(p)) {
    12.             personList.add(p);
    13.         }
    14.     }
    15. );
    16. System.out.println(personList);

    List 的contains()方法底层实现使用对象的equals方法去比较的,其实重写equals()就好,但重写了equals最好将hashCode也重写了。

    我们创建了一个高质量的技术交流群,与优秀的人在一起,自己也会优秀起来,赶紧点击加群,享受一起成长的快乐。

    可以参见:

    • http://stackoverflow.com/questions/30745048/how-to-remove-duplicate-objects-from-java-arraylist

    • http://blog.csdn.net/growing_tree/article/details/46622579

    三、根据对象的属性去重

    下面要根据Person对象的id去重,那该怎么做呢?

    写一个方法吧:

    1.   public static List<Person> removeDupliById(List<Person> persons) {
    2.         Set<Person> personSet = new TreeSet<>((o1, o2) -> o1.getId().compareTo(o2.getId()));
    3.         personSet.addAll(persons);
    4.         return new ArrayList<>(personSet);
    5.     }

    通过Comparator比较器,比较对象属性,相同就返回0,达到过滤的目的。

    再来看比较炫酷的Java8写法:

    1. import static java.util.Comparator.comparingLong;
    2. import static java.util.stream.Collectors.collectingAndThen;
    3. import static java.util.stream.Collectors.toCollection;
    4. // 根据id去重
    5. List<Person> unique = persons.stream().collect(
    6.     collectingAndThen(
    7.         toCollection(() -> new TreeSet<>(comparingLong(Person::getId))), ArrayList::new)
    8. );

    这段炫酷的代码是google的,还不明白是怎么个原理,等我好好研究一下,再专门写篇文章好好阐述一下。

    还有一种写法:

    1. public static <T> Predicate<T> distinctByKey(Function<? super TObjectkeyExtractor{
    2.     Map<ObjectBoolean> map = new ConcurrentHashMap<>();
    3.     return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    4. }
    5. // remove duplicate
    6. persons.stream().filter(distinctByKey(p -> p.getId())).forEach(p -> System.out.println(p));

    java8 确实简化了很多冗长的操作,精简了代码,小伙,研究java8去吧!

  • 相关阅读:
    前端离职工作项目交接清单
    区块链真的离不开预言机吗?
    从源码彻底理解 Prometheus/VictoriaMetrics 中的 relabel_configs/metric_relabel_configs 配置
    [量化投资-学习笔记008]Python+TDengine从零开始搭建量化分析平台-CCI和ATR
    JWT登录验证
    使用 docker 打包构建部署 Vue 项目,一劳永逸解决node-sass安装问题
    iOS开发之自定义的framework添加第三方framework,lipo和ar命令看.o文件
    12、填写NGINX配置部署前端;运行jar部署后端
    掌握这些你也可以拿offer到手软,让Java面试官佩服的没话说!
    上海某公司医疗实施工程师笔试题
  • 原文地址:https://blog.csdn.net/cpcpcp123/article/details/125410878