最好对java8新特性有一定的了解。可以参考:Java8新特性--流(Stream)
场景:有一个实体的List集合,需要根据实体中的某个字段对List去重
要想去重,可以考虑使用TreeSet。先来看看TreeSet的用法:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Dish {
private String id;
private String name;
}
private static List<Dish> dishList = new ArrayList<Dish>();
static {
Dish dish1 = new Dish("001", "张三");
dishList.add(dish1);
Dish dish2 = new Dish("001", "李四");
dishList.add(dish2);
Dish dish3 = new Dish("002", "王五");
dishList.add(dish3);
}
/**
* 测试TreeSet默认比较器及传入比较器
*/
@Test
public void testTreeSet() {
// TreeSet不传比较器,则默认按照自然顺序排序
TreeSet<Integer> treeSet = new TreeSet<>();
treeSet.add(3);
treeSet.add(1);
treeSet.add(4);
System.out.println(treeSet);
// [1, 3, 4]
// TreeSet中的元素,如果是实体,必须得传比较器(或者实体类需要实现Comparable中的compareTo方法),不然就会报错
// TreeSet是Set的子类,里面的元素有序且不能重复,可以去重
TreeSet<Dish> treeSet2 = new TreeSet<>(Comparator.comparing(Dish::getId));
treeSet2.addAll(dishList);
treeSet2.forEach(d -> System.out.println("id:" + d.getId() + ", name:" + d.getName()));
// id:001, name:张三
// id:002, name:王五
}
从上面可以看到TreeSet可以根据实体中的某个字段(这里是id)排序后去重。如果再将TreeSet转为List就可以达到我们的目的:
List<Dish> newDishList = new ArrayList<>(treeSet2);
newDishList.forEach(d -> System.out.println("id:" + d.getId() + ", name:" + d.getName()));
// id:001, name:张三
// id:002, name:王五
虽然大功告成,但是写这么一堆代码,好麻烦。可以使用java8中的收集器简化一下:
/**
* 测试Collectors.toCollection方法:将结果收集到其它类型的集合中(这里是TreeSet)
*/
@Test
public void testToCollection() {
TreeSet<Dish> treeSet2 = dishList.stream()
.collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Dish::getId))));
List<Dish> newDishList = new ArrayList<>(treeSet2);
newDishList.forEach(d -> System.out.println("id:" + d.getId() + ", name:" + d.getName()));
// id:001, name:张三
// id:002, name:王五
}
还可以再简单一点:
/**
* 测试Collectors.collectingAndThen方法:将流中的数据通过Collector计算,计算的结果再通过Function处理一下
* (这里是将TreeSet转为ArrayList。即相当于将最终结果又经过了new ArrayList<>(treeSet))
*/
@SuppressWarnings("unchecked")
@Test
public void testCollectingAndThen() {
List<Dish> newDishList = dishList.stream().collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Dish::getId))), ArrayList::new));
newDishList.forEach(d -> System.out.println("id:" + d.getId() + ", name:" + d.getName()));
// id:001, name:张三
// id:002, name:王五
}
知识改变世界