在學習本篇之前,最好對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:王五 }
