java8 Lambda Stream collect Collectors 經常使用實例

將一個對象的集合轉化成另外一個對象的集合  https://send.firefox.com/download/8a176f99db42673a/#M1frI1Q8OAo8bZVVcb1oKQhtml

List<OrderDetail> orderDetailList = orderDetailService.listOrderDetails();
List<CartDTO> cartDTOList = orderDetailList.stream()
                .map(e -> new CartDTO(e.getProductId(), e.getProductQuantity()))
                .collect(Collectors.toList());

交集 (list1 + list2)java

List<T> intersect = list1.stream()
                         .filter(list2::contains)
                         .collect(Collectors.toList());

差集app

//(list1 - list2)
List<String> reduce1 = list1.stream().filter(item -> !list2.contains(item)).collect(toList());

//(list2 - list1)
List<String> reduce2 = list2.stream().filter(item -> !list1.contains(item)).collect(toList());

並集函數

//使用並行流 
List<String> listAll = list1.parallelStream().collect(toList());
List<String> listAll2 = list2.parallelStream().collect(toList());
listAll.addAll(listAll2);

去重並集spa

List<String> listAllDistinct = listAll.stream()
.distinct().collect(Collectors.toList());

從List中過濾出一個元素.net

User match = users.stream()
.filter((user) -> user.getId() == 1).findAny().get();

Map集合轉 Listfirefox

List<Person> list = map.entrySet().stream().sorted(Comparator.comparing(e -> e.getKey()))
        .map(e -> new Person(e.getKey(), e.getValue())).collect(Collectors.toList());
        
List<Person> list = map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue)).map(e -> new Person(e.getKey(), e.getValue())).collect(Collectors.toList());

List<Person> list = map.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(e -> new Person(e.getKey(), e.getValue())).collect(Collectors.toList());

List集合轉 Map指針

/*使用Collectors.toMap形式*/
Map result = peopleList.stream().collect(Collectors.toMap(p -> p.name, p -> p.age, (k1, k2) -> k1));
//其中Collectors.toMap方法的第三個參數爲鍵值重複處理策略,若是不傳入第三個參數,當有相同的鍵時,會拋出一個IlleageStateException。
//或者
Map<Integer, String> result1 = list.stream().collect(Collectors.toMap(Hosting::getId, Hosting::getName));
//List<People> -> Map<String,Object>
List<People> peopleList = new ArrayList<>();
peopleList.add(new People("test1", "111"));
peopleList.add(new People("test2", "222"));
Map result = peopleList.stream().collect(HashMap::new,(map,p)->map.put(p.name,p.age),Map::putAll);

List 轉 Map<Integer,Apple>code

/**
 * List<Apple> -> Map<Integer,Apple>
 * 須要注意的是:
 * 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));

List 轉 List<Map<String,Object>>orm

List<Map<String,Object>> personToMap = peopleList.stream().map((p) -> {
    Map<String, Object> map = new HashMap<>();
    map.put("name", p.name);
    map.put("age", p.age);
    return map;
}).collect(Collectors.toList());
//或者
List<Map<String,Object>> personToMap = peopleList.stream().collect(ArrayList::new, (list, p) -> {
   Map<String, Object> map = new HashMap<>();
    map.put("name", p.name);
    map.put("age", p.age);
    list.add(map);
}, List::addAll);

 

Collectors toList

streamArr.collect(Collectors.toList());
List<Integer> collectList = Stream.of(1, 2, 3, 4)
        .collect(Collectors.toList());
System.out.println("collectList: " + collectList);
// 打印結果 collectList: [1, 2, 3, 4]

Collectors toMap

map value 爲對象 student
Map<Integer, Student> map = list.stream().collect(Collectors.toMap(Student::getId, student -> student));
// 遍歷打印結果
map.forEach((key, value) -> {
    System.out.println("key: " + key + "    value: " + value);
});
map value 爲對象中的屬性
Map<Integer, String> map = list.stream().collect(Collectors.toMap(Student::getId, Student::getName));
map.forEach((key, value) -> {
    System.out.println("key: " + key + "    value: " + value);
});

字典查詢和數據轉換 toMap時,若是value爲null,會報空指針異常

//方法一
Map<String, List<Dict>> resultMaps = Arrays.stream(dictTypes)
.collect(Collectors.toMap(i -> i, i -> Optional.ofNullable(dictMap.get(i)).orElse(new ArrayList<>()), (k1, k2) -> k2));
//方法二
Map<String, List<Dict>> resultMaps = Arrays.stream(dictTypes)
.filter(i -> dictMap.get(i) != null).collect(Collectors.toMap(i -> i, dictMap::get, (k1, k2) -> k2));

//方法三
Map<String, String> memberMap = list.stream().collect(HashMap::new, (m,v)->
    m.put(v.getId(), v.getImgPath()),HashMap::putAll);
System.out.println(memberMap);
//方法四
Map<String, String> memberMap = new HashMap<>();
list.forEach((answer) -> memberMap.put(answer.getId(), answer.getImgPath()));
System.out.println(memberMap);

Map<String, String> memberMap = new HashMap<>();
for (Member member : list) {
    memberMap.put(member.getId(), member.getImgPath());
}

假設有一個User實體類,有方法getId(),getName(),getAge()等方法,如今想要將User類型的流收集到一個Map中,示例以下:

Stream<User> userStream = Stream.of(new User(0, "張三", 18), new User(1, "張四", 19), new User(2, "張五", 19), new User(3, "老張", 50));

Map<Integer, User> userMap = userSteam.collect(Collectors.toMap(User::getId, item -> item));

假設要獲得按年齡分組的Map<Integer,List>,能夠按這樣寫:

Map<Integer, List<User>> ageMap = userStream.collect(Collectors.toMap(User::getAge, Collections::singletonList, (a, b) -> {
            List<User> resultList = new ArrayList<>(a);
            resultList.addAll(b);
            return resultList;
        }));

Map<Integer, String> map = persons
    .stream()
    .collect(Collectors.toMap(
        p -> p.age,
        p -> p.name,
        (name1, name2) -> name1 + ";" + name2));

System.out.println(map);
// {18=Max, 23=Peter;Pamela, 12=David}

Map 轉 另外一個Map

//示例1 Map<String, List<String>> 轉 Map<String,User>
Map<String,List<String>> map = new HashMap<>();
map.put("java", Arrays.asList("1.7", "1.8"));
map.entrySet().stream();

@Getter
@Setter
@AllArgsConstructor
public static class User{
    private List<String> versions;
}

Map<String, User> collect = map.entrySet().stream()
                .collect(Collectors.toMap(
                        item -> item.getKey(),
                        item -> new User(item.getValue())));

//示例2 Map<String,Integer>  轉 Map<String,Double>
Map<String, Integer> pointsByName = new HashMap<>();
Map<String, Integer> maxPointsByName = new HashMap<>();

Map<String, Double> gradesByName = pointsByName.entrySet().stream()
        .map(entry -> new AbstractMap.SimpleImmutableEntry<>(
                entry.getKey(), ((double) entry.getValue() /
                        maxPointsByName.get(entry.getKey())) * 100d))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

Collectors toSet

Set<String> result = Stream.of("aa", "bb", "cc", "aa").collect(HashSet::new, HashSet::add, HashSet::addAll);
//Collectors類中已經預約義好了toList,toSet,toMap,toCollection等方便使用的方法,因此以上代碼還能夠簡化以下:
Set<String> result2 = Stream.of("aa", "bb", "cc", "aa").collect(Collectors.toSet());

Set<Integer> collectSet = Stream.of(1, 2, 3, 4).collect(Collectors.toSet());
System.out.println("collectSet: " + collectSet);
// 打印結果 collectSet: [1, 2, 3, 4]

Stack stack1 = stream.collect(Collectors.toCollection(Stack::new));
// collect toString
String str = stream.collect(Collectors.joining()).toString();

Collectors groupingBy

Map<Integer, List<User>> ageMap2 = userStream
.collect(Collectors.groupingBy(User::getAge));
//groupingBy 分組後操做
//Collectors中還提供了一些對分組後的元素進行downStream處理的方法:
//counting方法返回所收集元素的總數;
//summing方法會對元素求和;
//maxBy和minBy會接受一個比較器,求最大值,最小值;
//mapping函數會應用到downstream結果上,並須要和其餘函數配合使用;

Map<Integer, Long> sexCount = userStream.collect(Collectors.groupingBy(User::getSex,Collectors.counting()));

Map<Integer, Integer> ageCount = userStream.collect(Collectors.groupingBy(User::getSex,Collectors.summingInt(User::getAge)));

Map<Integer, Optional<User>> ageMax =  userStream.collect(Collectors.groupingBy(User::getSex,Collectors.maxBy(Comparator.comparing(User::getAge))));

Map<Integer, List<String>> nameMap =  userStream.collect(Collectors.groupingBy(User::getSex,Collectors.mapping(User::getName,Collectors.toList())));

groupingBy 根據年齡來分組:

Map<Integer, List> peopleByAge = peoples.stream()
.filter(p -> p.age > 12).collect(Collectors.groupingBy(p -> p.age, Collectors.toList()));

groupingBy 根據年齡分組,年齡對應的鍵值List存儲的爲Person的姓名:

Map<Integer, List> peopleByAge = people.stream()
.collect(Collectors.groupingBy(p -> p.age, Collectors.mapping((Person p) -> p.name, Collectors.toList())));
//mapping即爲對各組進行投影操做,和Stream的map方法基本一致。

groupingBy 根據姓名分組,獲取每一個姓名下人的年齡總和:

Map sumAgeByName = peoples.stream().collect(Collectors.groupingBy(p -> p.name, Collectors.reducing(0, (Person p) -> p.age, Integer::sum)));
/* 或者使用summingInt方法 */
sumAgeByName = peoples.stream().collect(Collectors.groupingBy(p -> p.name, Collectors.summingInt((Person p) -> p.age)));

groupingBy Boolean分組:

Map<Boolean, List<Integer>> collectGroup = Stream.of(1, 2, 3, 4)
            .collect(Collectors.groupingBy(it -> it > 3));
System.out.println("collectGroup : " + collectGroup);
// 打印結果
// collectGroup : {false=[1, 2, 3], true=[4]}

groupingBy 按年齡分組

Map<Integer, List<Person>> personsByAge = persons.stream().collect(Collectors.groupingBy(p -> p.age));
personsByAge.forEach((age, p) -> System.out.format("age %s: %s\n", age, p));
// age 18: [Max]
// age 23: [Peter, Pamela]
// age 12: [David]

Collectors partitioningBy

Collectors中還提供了partitioningBy方法,接受一個Predicate函數,該函數返回boolean值,用於將內容分爲兩組。假設User實體中包含性別信息getSex(),能夠按以下寫法將userStream按性別分組:

Map<Boolean, List<User>> sexMap = userStream
.collect(Collectors.partitioningBy(item -> item.getSex() > 0));

能夠看到Java8的分組功能至關強大,固然你還能夠完成更復雜的功能。另外Collectors中還存在一個相似groupingBy的方法:partitioningBy,它們的區別是partitioningBy爲鍵值爲Boolean類型的groupingBy,這種狀況下它比groupingBy更有效率。

partitioningBy 將數字的Stream分解成奇數集合和偶數集合。

Map<Boolean, List<Integer>> collectParti = Stream.of(1, 2, 3, 4)
            .collect(Collectors.partitioningBy(it -> it % 2 == 0));
System.out.println("collectParti : " + collectParti);
// 打印結果
// collectParti : {false=[1, 3], true=[2, 4]}

Collectors joining
Collectors.joining 收集Stream中的值,該方法能夠方便地將Stream獲得一個字符串。joining函數接受三個參數,分別表示允(用以分隔元素)、前綴和後綴:

String names = peoples.stream().map(p->p.name).collect(Collectors.joining(","))

String strJoin = Stream.of("1", "2", "3", "4")
        .collect(Collectors.joining(",", "[", "]"));
System.out.println("strJoin: " + strJoin);
// 打印結果
// strJoin: [1,2,3,4]

//字符串鏈接
String phrase = persons
    .stream()
    .filter(p -> p.age >= 18)
    .map(p -> p.name)
    .collect(Collectors.joining(" and ", "In Germany ", " are of legal age."));
System.out.println(phrase);
// In Germany Max and Peter and Pamela are of legal age.

Collectors分別提供了求平均值averaging、總數couting、最小值minBy、最大值maxBy、求和suming等操做。可是假如你但願將流中結果聚合爲一個總和、平均值、最大值、最小值,那麼Collectors.summarizing(Int/Long/Double)就是爲你準備的,它能夠一次行獲取前面的全部結果,其返回值爲(Int/Long/Double)SummaryStatistics。

DoubleSummaryStatistics dss = people.collect(Collectors.summarizingDouble((Person p)->p.age));
double average=dss.getAverage();
double max=dss.getMax();
double min=dss.getMin();
double sum=dss.getSum();
double count=dss.getCount();

IntSummaryStatistics ageSummary = persons
        .stream()
        .collect(Collectors.summarizingInt(p -> p.age));

System.out.println(ageSummary);
// IntSummaryStatistics{count=4, sum=76, min=12, average=19.000000, max=23}

使用collect能夠將Stream轉換成值。maxBy和minBy容許用戶按照某個特定的順序生成一個值。

averagingDouble:求平均值,Stream的元素類型爲double

averagingInt:求平均值,Stream的元素類型爲int

averagingLong:求平均值,Stream的元素類型爲long

counting:Stream的元素個數

maxBy:在指定條件下的,Stream的最大元素

minBy:在指定條件下的,Stream的最小元素

reducing: reduce操做

summarizingDouble:統計Stream的數據(double)狀態,其中包括count,min,max,sum和平均。

summarizingInt:統計Stream的數據(int)狀態,其中包括count,min,max,sum和平均。

summarizingLong:統計Stream的數據(long)狀態,其中包括count,min,max,sum和平均。

summingDouble:求和,Stream的元素類型爲double

summingInt:求和,Stream的元素類型爲int

summingLong:求和,Stream的元素類型爲long

Optional<Integer> collectMaxBy = Stream.of(1, 2, 3, 4)
            .collect(Collectors.maxBy(Comparator.comparingInt(o -> o)));
System.out.println("collectMaxBy:" + collectMaxBy.get());
// 打印結果
// collectMaxBy:4

Collectors averagingInt計算平均值

Double averageAge = persons
    .stream()
    .collect(Collectors.averagingInt(p -> p.age));

System.out.println(averageAge);     // 19.0

原文閱讀   傳參

相關文章
相關標籤/搜索