Java8 Lambda表达式实现集合去重

去重操作是开发中经常会碰到的问题,可以自己写一个,也可以直接用Java提供的集合API来实现,毕竟它数据结构和算法都是最优的,所以可以直接拿来用。

众所周知,Java的集合Set有去重的作用。它有很多子类,最常用的就是HashSet和TreeSet。HashSet是无序的,TreeSet则是有序的。


看一个HashSet的简单例子

public class Test {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(1);
        list.add(3);
        HashSet hashSet = new HashSet<>(list);
        hashSet.stream().forEach(e -> System.out.println(e));
    }
}

可以实现去重。我们必须还要保证原有集合中的元素顺序,所以必须使用TreeSet。

TreeSet 描述文档

The elements are ordered using their {@linkplain Comparable natural
ordering}, or by a {@link Comparator} provided at set creation
time, depending on which constructor is used

它有两种排序,一种是自然排序,一种是在构造集合的时候,一种是通过Comparator指定排序。看一下它的构造函数:

public TreeSet(Comparator<? super E> comparator) {
    this(new TreeMap<>(comparator));
}

测试

public static void main(String[] args) {
        Map<String,String> map1 = new HashMap<>();
        map1.put("id","1");
        map1.put("name","张三");

        Map<String,String> map2 = new HashMap<>();
        map2.put("id","1");
        map2.put("name","李四");

        Map<String,String> map3 = new HashMap<>();
        map3.put("id","2");
        map3.put("name","王五");

        TreeSet<Map<String,String>> treeSet = new TreeSet<>(Comparator.comparing(map -> String.valueOf(map.get("id"))));
        treeSet.add(map1);
        treeSet.add(map2);
        treeSet.add(map3);
        treeSet.stream().forEach(map -> System.out.println(map.get("id") + "==" + map.get("name")));
}

控制台打印

可以看到,放入treeSet中的元素根据id去重了。


上面的TreeSet是一个一个把元素插进去的,现在结合Lambda表达式的函数式接口进行流式编写,对上面的代码进行改造:

public static void main(String[] args) {
    Map<String,String> map1 = new HashMap<>();
    map1.put("id","1");
    map1.put("name","张三");

    Map<String,String> map2 = new HashMap<>();
    map2.put("id","1");
    map2.put("name","李四");

    Map<String,String> map3 = new HashMap<>();
    map3.put("id","2");
    map3.put("name","王五");

    List<Map<String, String>> list = new ArrayList<>();
    list.add(map1);
    list.add(map2);
    list.add(map3);

    list.stream()
        .collect(Collectors.collectingAndThen(
            Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(
                    s -> String.valueOf(s.get("id"))))), ArrayList::new));
}

流式编写的代码阅读起来确实不方便,而且调试起来也不方便,但它却大大减少代码行数,写起来很有感觉,一气呵成。把上面的代码分开看,就容易理解。

new TreeSet 这一部分就不看,上面已经说过了,就是构造了TreeSet实例。主要看两个函数:

第一个函数

public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,
                                                                Function<R,RR> finisher)

 简单来说就把一个集合结构调整为另一个集合结构。例如把一个可变的List变成一个不可变的List。就如文档中写的这个Demo.

List<String> people = people.stream().collect(collectingAndThen(toList(),Collections::unmodifiableList));

第二个函数

public static <T, C extends Collection<T>>
    Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
        return new CollectorImpl<>(collectionFactory, Collection<T>::add,
                                   (r1, r2) -> { r1.addAll(r2); return r1; },
                                   CH_ID);
}

对输入的元素进行计算并放入一个新的集合。新的集合就是我们上面说的那个TreeSet。


总结

集合中的元素就像流水,把一个水桶中水流入另一个水桶,中间有一个净化器。Lambda就像这个净化器。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值