今天來學習最后一個操作方法collect
日常流式操作后,需要對結(jié)果處理,則可以用這個方法來實現(xiàn)。
collect(Collector<? super P_OUT, A, R> collector)
這里我們首先要學一下Collectors這個類,這個類里有個靜態(tài)內(nèi)部類是Collector的實現(xiàn)類,也就是說,Collectors類里的靜態(tài)方法內(nèi)部實現(xiàn)都是基于Collector的實現(xiàn)類
Collectors.toCollection(Supplier<C> collectionFactory)
這個方法將流收集為一個實現(xiàn)了collection接口的容器類.如下所示,將一個流轉(zhuǎn)化為一個hashSet.只要是collection接口的實現(xiàn)類,都可以在這里輕松轉(zhuǎn)換。
HashSet<Integer> collect =Stream.of(2,3,6,8).collect(Collectors.toCollection(HashSet::new));
toList()
這個不多說,就是直接將流轉(zhuǎn)化為一個Arraylist對象
toSet()
這個也不多說,轉(zhuǎn)化為一個hashSet對象
joining()
這個不多說,將流中的元素拼接成字符串。流中的元素首先必須先轉(zhuǎn)換為string類型。字符串的拼接是通過StringBuilder::append完成的。
String collect = Stream.of("hello", " ", "world").collect(Collectors.joining());
輸出:hello world
joining(分隔符)
這個可以指定分割符號來進行字符串拼接。下面的代碼結(jié)果同上
String collect = Stream.of("hello", "world").collect(Collectors.joining(" "));
輸出:hello world
joining(分隔符,前綴,后綴)
這里方法里面可以指定分隔符,然后可以指定字符串的前綴,后綴
String collect = Stream.of("hello", "world").collect(Collectors.joining(",","{","}"));
輸出:{hello,world}
mapping(Function<? super T, ? extends U> mapper,Collector<? super U, A, R> downstream) 函數(shù)
這個函數(shù)從源碼的功能來看,mapping函數(shù)接收2個參數(shù),第一個參數(shù)就是一個運算式,第二個參數(shù)是接受第一個參數(shù)運算后的結(jié)果,可以繼續(xù)用Collector去處理。明白了這個數(shù)據(jù)的流向,那么我們來看看怎么用
比如:有一個字符串數(shù)組,想把字符串數(shù)組先轉(zhuǎn)成大寫,然后在拼接。可以有2種實現(xiàn)方式。下面的上下兩種方式效果是一樣的。
String collect = Stream.of("a","b","c").map(s->s.toUpperCase()).collect(Collectors.joining());
String collect1 = Stream.of("a","b","c").collect(Collectors.mapping(s -> s.toUpperCase(), Collectors.joining()));
System.out.println(collect);
System.out.println(collect1);
collectingAndThen(Collector<T,A,R> downstream,Function<R,RR> finisher)
見名知意,這個操作先把結(jié)果可以用自身函數(shù)處理一遍,然后可以繼續(xù)用第二個函數(shù)把之前一補處理完的函數(shù)繼續(xù)用新函數(shù)再次進行運算
比如如下圖,將一個流處理完成后,想變成一個不可再次一被操作的集合,可以通過下列方式去完成。就是第一個參數(shù)處理的結(jié)果,作為第二個行為參數(shù)的入?yún)?,且一定是一個接受一個入?yún)?,然后進過運算有返回值的一個行為函數(shù),最終結(jié)果是以第二個行為函數(shù)操作的結(jié)果。
Collection<String> collect = Stream.of("a", "b", "c").collect(Collectors.collectingAndThen(Collectors.toList(), a -> Collections.unmodifiableCollection(a)));
System.out.println(collect);
輸出結(jié)果是一個不支持修改的集合。
counting 函數(shù),是一個統(tǒng)計函數(shù),返回流中元素的個數(shù)。
Long collect = Stream.of("a", "b", "c").collect(Collectors.counting());
System.out.println(collect);
輸出結(jié)果是3,代表流中元素個數(shù)是3個
minBy maxBy 分別返回流中按照傳入的比較規(guī)則返回最大最小值。
Optional<Person> collect = Stream.of(new Person("a", 11), new Person("b", 12), new Person("c", 22)).collect(Collectors.minBy((a, b) -> a.getAge() - b.getAge()));
Optional<Person> collect1 = Stream.of(new Person("a", 11), new Person("b", 12), new Person("c", 22)).collect(Collectors.minBy((a, b) -> b.getAge() - a.getAge()));
System.out.println(JSONObject.toJSONString(collect.get()));
System.out.println(JSONObject.toJSONString(collect1.get()));
操作返回結(jié)果是:
{"age":11,"name":"a"}
{"age":22,"name":"c"}
summingInt() summingLong() summingDouble()
需要傳入一個基本類型的數(shù)字,然后這個函數(shù)會對傳入的數(shù)字進行求和。
如下所示,有3個Person對象,想知道這三個對象的年齡和是多少,則可以通過這個函數(shù)來進行運算。運算過程如下,流中的每一個元素會傳入到函數(shù)中,然后傳入的對象需要轉(zhuǎn)換成對于的基本類型,函數(shù)會將基本類型進行求和。
Integer collect = Stream.of(new Person("a", 11), new Person("b", 12), new Person("c", 22)).
collect(Collectors.summingInt(value -> value.getAge()));
System.out.println(collect);
操作返回結(jié)果是:
45
averagingInt() averagingLong() averagingDouble()
需要傳入對應的基本類型,然后函數(shù)內(nèi)部會對傳入的數(shù)字進行求平均. 原理同上,需要將傳入的對象轉(zhuǎn)換為對應的基本類型,最后進行求平均
reducing()
這個函數(shù)和reduce函數(shù)的用法是一樣的。這里再次用3個demo來說明下
一個參數(shù):
Optional<Person> collect = Stream.of(new Person("張三", 13), new Person("李四", 13)).
collect(Collectors.reducing(BinaryOperator.minBy(Comparator.comparing(Person::getAge))));
System.out.println(collect.get());
2個參數(shù):
Integer collect = Stream.of(1,2,3,4,5).
collect(Collectors.reducing(0,(a,b) -> a+b));
System.out.println(collect);
3個參數(shù):
ArrayList<Integer> integers = Lists.newArrayList(1, 2, 3, 4, 5);
Integer collect = integers.parallelStream().
collect(Collectors.reducing(0, e -> (Integer) e, (c, d) -> c + d));
System.out.println(collect);
groupingBy 分組函數(shù)
分組函數(shù)的目標很簡單,就是基于一定的規(guī)則進行分組。如下所示,對流中的數(shù)據(jù)進行奇數(shù)和偶數(shù)分組。
ArrayList<Integer> integers = Lists.newArrayList(1, 2, 3, 4, 5,6);
Map<Integer, List<Integer>> collect = integers.stream().
collect(Collectors.groupingBy(a -> (a)%2));
System.out.println(collect);
輸出結(jié)果如下:{0=[2, 4, 6], 1=[1, 3, 5]}
groupingByConcurrent 很簡單,就是分組后返回一個concurrentMap
這個用法和普通的groupingby是一樣的用法,傳入一個分組的標準。比如按人的年齡分組。如下:
ArrayList<Person> persons = Lists.newArrayList(new Person("a",11),new Person("b",12),new Person("c",11),new Person("b",14));
ConcurrentMap<Integer, List<Person>> collect = persons.stream().
collect(Collectors.groupingByConcurrent(a -> a.getAge()));
System.out.println(JSONObject.toJSONString(collect));
輸出如下:
{11:[{"age":11,"name":"a"},{"age":11,"name":"c"}],12:[{"age":12,"name":"b"}],14:[{"age":14,"name":"b"}]}
partitioningBy 和groupingby返回的不一樣的地方在于,返回的是一個key為布爾類型的key,也就是只能返回true,false兩個key。
比如有幾個人,判斷是否是成年人。
ArrayList<Person> persons = Lists.newArrayList(new Person("a",11),new Person("b",12),new Person("c",18),new Person("b",19));
Map<Boolean, List<Person>> collect = persons.stream().
collect(Collectors.partitioningBy(a -> a.getAge() > 17));
System.out.println(JSONObject.toJSONString(collect));
輸出結(jié)果如下:
{false:[{"age":11,"name":"a"},{"age":12,"name":"b"}],true:[{"age":18,"name":"c"},{"age":19,"name":"b"}]}
toMap 這個可以將流轉(zhuǎn)換成map.
比如同樣還是上面4個人,想用年齡做key,名字做value。成功的將一個對象的list轉(zhuǎn)換成某2個屬性的map集合
ArrayList<Person> persons = Lists.newArrayList(new Person("a",11),new Person("b",12),new Person("c",18),new Person("b",19));
Map<Integer, String> collect = persons.stream().
collect(Collectors.toMap(a -> a.getAge(), b -> b.getName()));
System.out.println(JSONObject.toJSONString(collect));
輸出如下:
{18:"c",19:"b",11:"a",12:"b"}
toConcurrentMap 這個和上面一樣,只是返回的是ConcurrentMap
summarizingInt 統(tǒng)計類型類操作??梢詫⒘髦械脑剞D(zhuǎn)換成int類型。返回一個IntSummaryStatistics對象。這個對象可以做統(tǒng)計,求平均數(shù),最大,最小,和等操作。
比如想求上面列表中人的年齡之和。平均數(shù),最大年齡,最小年齡
ArrayList<Person> persons = Lists.newArrayList(new Person("a",11),new Person("b",12),new Person("c",18),new Person("b",19));
IntSummaryStatistics collect = persons.stream().
collect(Collectors.summarizingInt(a -> a.getAge()));
System.out.println(collect.getAverage());
System.out.println(collect.getCount());
System.out.println(collect.getMax());
System.out.println(collect.getMin());
System.out.println(collect.getSum());
這里流操作基本就學完了。