使用Stream快速對List進行一些操作


首先定義一個 Apple 類,示例如下:

public class Apple {
    private Integer id;
    private String name;
    private BigDecimal money;
    private Integer num;
    public Apple(Integer id, String name, BigDecimal money, Integer num) {
        this.id = id;
        this.name = name;
        this.money = money;
        this.num = num;
    }
}

然后添加一些測試數據:

List<Apple> appleList = new ArrayList<>();  //存放apple對象集合
 
Apple apple1 =  new Apple(1,"蘋果1",new BigDecimal("3.25"),10);
Apple apple12 = new Apple(1,"蘋果2",new BigDecimal("1.35"),20);
Apple apple2 =  new Apple(2,"香蕉",new BigDecimal("2.89"),30);
Apple apple3 =  new Apple(3,"荔枝",new BigDecimal("9.99"),40);
 
appleList.add(apple1);
appleList.add(apple12);
appleList.add(apple2);
appleList.add(apple3);

1. 排序

可以使用 sort 方法對對象中的單字段或者多字段進行排序:

//排序
//單字段排序,根據id排序
appleList.sort(Comparator.comparing(Apple::getId));

//多字段排序,根據id,數量排序
appleList.sort(Comparator.comparing(Apple::getId).thenComparing(User::getNum));

2. 分組

可快速對 List 中的對象元素以對象的某一屬性進行分類,比如以 ID 進行分組,將 ID 相同的對象放在一起,那么可以直接這么做:

//List 以ID分組 Map<Integer,List<Apple>>
Map<Integer, List<Apple>> groupBy = appleList.stream().collect(Collectors.groupingBy(Apple::getId));
 
System.out.println("groupBy:" + groupBy);
{1=[Apple{id=1, name='蘋果1', money=3.25, num=10}, Apple{id=1, name='蘋果2', money=1.35, num=20}], 2=[Apple{id=2, name='香蕉', money=2.89, num=30}], 3=[Apple{id=3, name='荔枝', money=9.99, num=40}]}

3. List 轉 Map

這是一個會用到的常用操作,比如 List 中存放的 Apple 對象,現在要轉換成 ID 為鍵,對象為值的 Map,那么可以直接這么操作:

/**
 * List -> Map
 * 需要注意的是:
 * toMap 如果集合對象有重復的key,會報錯 Duplicate key ....
 *  apple1,apple12的id都為 1。
 *  可以用 (k1,k2)->k1 來設置,如果有重復的key,則保留key1,舍棄key2
 */
Map<Integer, Apple> appleMap = appleList.stream().collect(Collectors.toMap(Apple::getId, a -> a,(k1,k2)->k1));

然后我們打印 Map 結果:

{1=Apple{id=1, name='蘋果1', money=3.25, num=10}, 2=Apple{id=2, name='香蕉', money=2.89, num=30}, 3=Apple{id=3, name='荔枝', money=9.99, num=40}}

4. 過濾查找元素

這個也使用的比較頻繁,比如我們要從 List 中找到名稱為香蕉的對象,那么可以這么操作:

//過濾出符合條件的數據
List<Apple> filterList = appleList.stream().filter(a -> a.getName().equals("香蕉")).collect(Collectors.toList());
 
System.out.println("filterList:"+filterList);
[Apple{id=2, name='香蕉', money=2.89, num=30}]

5. 求和

將集合中的數據按照某個屬性求和,如果是基本類型,可以使用 mapToInt 然后調用 sum 方法,如果是大樹則使用 reduce 並調用 BigDecimal::add 方法。

//計算 總金額

//基本類型
int total = appleList.stream().mapToInt(Apple::getMoney).sum();

//大數
BigDecimal totalMoney = appleList.stream().map(Apple::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
System.out.println("totalMoney:" + totalMoney);  //totalMoney:17.48

注意,上面的求和不能過濾 BigDecimal 對象為 null 的情況,可能會報空指針,這種情況,我們可以用 filter 方法過濾,或者重寫求和方法。

6. 查找流中最大/小值

利用 Collectors.maxBy 和 Collectors.minBy 來計算流中的最大或最小值。

Optional<Dish> maxDish = Dish.menu.stream().
      collect(Collectors.maxBy(Comparator.comparing(Dish::getCalories)));
maxDish.ifPresent(System.out::println);
 
Optional<Dish> minDish = Dish.menu.stream().
      collect(Collectors.minBy(Comparator.comparing(Dish::getCalories)));
minDish.ifPresent(System.out::println);

7. 根據屬性去重

import static java.util.Comparator.comparingLong;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;
 
// 根據id去重
List<Person> unique = appleList.stream().collect(
            collectingAndThen(
                toCollection(() -> new TreeSet<>(comparingLong(Apple::getId))), ArrayList::new)
        );

8. 獲取交集/並集/差集/去重並集

import static java.util.stream.Collectors.toList;
import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args) {
        List<String> list1 = new ArrayList();
        list1.add("1111");
        list1.add("2222");
        list1.add("3333");

        List<String> list2 = new ArrayList();
        list2.add("3333");
        list2.add("4444");
        list2.add("5555");

        // 交集     拓展:list2里面如果是對象,則需要提取每個對象的某一屬性組成新的list,多個條件則為多個list
        List<String> intersection = list1.stream().filter(item -> list2.contains(item)).collect(Collectors.toList());
        System.out.println("---得到交集 intersection---");
        intersection.parallelStream().forEach(System.out :: println);

        // 差集 (list1 - list2)    同上拓展
        List<String> reduce1 = list1.stream().filter(item -> !list2.contains(item)).collect(Collectors.toList());
        System.out.println("---得到差集 reduce1 (list1 - list2)---");
        reduce1.parallelStream().forEach(System.out :: println);

        // 差集 (list2 - list1)
        List<String> reduce2 = list2.stream().filter(item -> !list1.contains(item)).collect(Collectors.toList());
        System.out.println("---得到差集 reduce2 (list2 - list1)---");
        reduce2.parallelStream().forEach(System.out :: println);

        // 並集
        List<String> listAll = list1.parallelStream().collect(toList());
        List<String> listAll2 = list2.parallelStream().collect(Collectors.toList());
        listAll.addAll(listAll2);
        System.out.println("---得到並集 listAll---");
        listAll.parallelStream().forEach(System.out :: println);

        // 去重並集
        List<String> listAllDistinct = listAll.stream().distinct().collect(Collectors.toList());
        System.out.println("---得到去重並集 listAllDistinct---");
        listAllDistinct.parallelStream().forEach(System.out :: println);

        System.out.println("---原來的List1---");
        list1.parallelStream().forEach(System.out :: println);
        System.out.println("---原來的List2---");
        list2.parallelStream().forEach(System.out :: println);

        // 一般有filter 操作時,不用並行流parallelStream ,如果用的話可能會導致線程安全問題

    }
}

 9.根據list里的對象去重操作

1、根據對象中某個屬性去重

1.1、創建提取方法

private <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
    Map<Object, Boolean> concurrentHashMap = new ConcurrentHashMap<>();
    return t -> concurrentHashMap.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}

1.2、利用filter

List<TestCommodity> codeDistinctList = testCommodityList
            .stream()
            .filter(distinctByKey(TestCommodity::getCode))
            .collect(Collectors.toList());

2、根據對象中多個個屬性去重,利用collectingAndThen

List<TestCommodity> cbList = testCommodityList
            .stream()
            .collect(
                    Collectors.collectingAndThen(
                            Collectors.toCollection(
                            () -> new TreeSet<>(
                                    Comparator.comparing(
                                            tc -> tc.getCode() + ";" + tc.getBarCode()))), ArrayList::new));

 

摘自:https://bestzuo.cn/posts/stream-list.html#1-%E6%8E%92%E5%BA%8F


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM