In 一起来学Java8(七)——Stream(上)
, we learned a Stream object common methods and usage. Now take a deep knowledge of the Stream.collect()
use of
collect basic usage
means to collect the collection, which is the Stream elements collected and grouped, a new collection of objects returned. First look at a simple example:
public class CollectTest {
@Data
@AllArgsConstructor
static class Goods {
private String goodsName;
private int price;
}
public static void main(String[] args) {
List<Goods> list = Arrays.asList(
new Goods("iphoneX", 4000)
, new Goods("mate30 pro", 5999)
, new Goods("redmek20", 2999)
);
List<String> nameList = list.stream()
.map(Goods::getGoodsName)
.collect(Collectors.toList());
}
}复制代码
In this example, the trade name returned by the map method, and then put all the trade names into the List object.
View source found, collect process consists of two overloaded methods composition.
- method 1:
<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);复制代码
- Method 2:
<R, A> R collect(Collector<? super T, A, R> collector);复制代码
Wherein the most widely used is a method 2, this method can be seen as a shortcut method, because Collector likewise provided these three parameters, it is easy to guess, or to use the underlying process corresponding implementation.Supplier
We can start with collect(Collector
collector)
the beginning to start, go through this process of getting to know the usage.
Collectors
Stream.collect(Collector
collector)
Collector Parameters object method mainly Collectors
provides classes. Collectors class which contains a series of static method, returns Collector for the object, a method commonly used as listed below:
Method name | description |
---|---|
averagingXX | Averaging |
counting | Seeking the number of elements in the set |
groupingBy | The collection group |
joining | Collection element splicing |
mapping | Can be re-mapped values during packet |
maxBy | Seeking maximum |
minBy | For the minimum |
partitioningBy | Partition the elements |
reducing | induction |
summarizingXX | Gather |
toCollection | Converted into a collection of objects |
toConcurrentMap | Converted into ConcurrentMap |
toList | Convert List |
toMap | Converted into a Map |
toSet | Converted into a Set |
Here we turn off his usefulness in terms of each method.
averagingXX
averagingXX including averagingDouble, averagingInt, averagingLong. They represent averaged.
double averagingInt = Stream.of(1, 2, 3)
.collect(Collectors.averagingInt(val -> val));
System.out.println("averagingInt:" + averagingInt);
double averagingLong = Stream.of(10L, 21L, 30L)
.collect(Collectors.averagingLong(val -> val));
System.out.println("averagingLong:" + averagingLong);
double averagingDouble = Stream.of(0.1, 0.2, 0.3)
.collect(Collectors.averagingDouble(val -> val));
System.out.println("averagingDouble:" + averagingDouble);复制代码
Their parameters are a function interface, you can be prepared using a Lambda expression, wherein expression Lambda Stream parameters of elements, returns a value to be averaged. This is below the average of commodity Liezi is seeking:
List<Goods> list = Arrays.asList(
new Goods("iphoneX", 4000)
, new Goods("mate30 pro", 5999)
, new Goods("redmek20", 2999)
);
double avgPrice = list.stream()
.collect(Collectors.averagingInt(goods -> goods.getPrice()));
System.out.println("商品的平均价格:" + avgPrice);复制代码
summingXX
And averagingXX Similarly, summingXX element method is used to find the sum of the values set.
double summingInt = Stream.of(1, 2, 3)
.collect(Collectors.summingInt(val -> val));
System.out.println("summingInt:" + summingInt);
double summingLong = Stream.of(10L, 21L, 30L)
.collect(Collectors.summingLong(val -> val));
System.out.println("summingLong:" + summingLong);
double summingDouble = Stream.of(0.1, 0.2, 0.3)
.collect(Collectors.summingDouble(val -> val));
System.out.println("summingDouble:" + summingDouble);复制代码
print:
summingInt:6.0
summingLong:61.0
summingDouble:0.6复制代码
counting()
Counting () returns the number of elements in a collection.
long count = Stream.of(1,2,3,4,5)
.collect(Collectors.counting());
System.out.println("count:" + count); // 5复制代码
summarizingXX
The above talked about averagingXX (averaging), summingXX (sum), counting (total demand), if I want to get all three at the same time the number of how to do it, you can use summarizingXX.
IntSummaryStatistics summarizingInt = Stream.of(1, 2, 3)
.collect(Collectors.summarizingInt(val -> val));
System.out.println("平均值:" + summarizingInt.getAverage());
System.out.println("总个数:" + summarizingInt.getCount());
System.out.println("总和:" + summarizingInt.getSum());
System.out.println("最大值:" + summarizingInt.getMax());
System.out.println("最小值:" + summarizingInt.getMin());复制代码
print:
平均值:2.0
总个数:3
总和:6
最大值:3
最小值:1复制代码
summarizingInt the statistical results into a IntSummaryStatistics objects inside, it can obtain different statistical information in the object.
groupingBy()
groupingBy () is a set of elements grouped by the three overloaded methods composition
- Overload 1: groupingBy (Function)
- Overload 2: groupingBy (Function, Collector)
- 重载3: groupingBy(Function, Supplier, Collector)
Overload overloaded call 1 wherein 2, 3 overloaded call the overloaded 2, thus eventually implemented to be overloaded 3.
First, a look overloaded groupingBy(Function)
usage, this method of default packets to the new List, the following example of this type of product are grouped into the same type of goods in a List.
@Data
@AllArgsConstructor
static class Goods {
private String goodsName;
// 类型,1:手机,2:电脑
private int type;
@Override
public String toString() {
return goodsName;
}
}
public static void main(String[] args) {
List<Goods> list = Arrays.asList(
new Goods("iphoneX", 1)
, new Goods("mate30 pro", 1)
, new Goods("thinkpad T400", 2)
, new Goods("macbook pro", 2)
);
Map<Integer, List<Goods>> goodsListMap = list.stream()
.collect(Collectors.groupingBy(Goods::getType));
goodsListMap.forEach((key, value) -> {
System.out.println("类型" + key + ":" + value);
});
}复制代码
print:
类型1:[iphoneX, mate30 pro]
类型2:[thinkpad T400, macbook pro]复制代码
Speaking of the above groupingBy(Function)
is actually called groupingBy(Function, Collector)
, where the second parameter Collector
determines the conversion to where, by default toList()
, see groupingBy(Function)
the source code:
public static <T, K> Collector<T, ?, Map<K, List<T>>>
groupingBy(Function<? super T, ? extends K> classifier) {
return groupingBy(classifier, toList());
}复制代码
So we can call groupingBy(Function, Collector)
manually specify the Collector, assuming that the elements we need to convert them into Set, you can write:
Map<Integer, Set<Goods>> goodsListMap = list.stream()
.collect(Collectors.groupingBy(Goods::getType, Collectors.toSet()));复制代码
View overloaded method Source 2, found its calling overloaded 3:
public static <T, K, A, D>
Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
Collector<? super T, A, D> downstream) {
return groupingBy(classifier, HashMap::new, downstream);
}复制代码
Wherein Goods::getType
the corresponding classifier, Collectors.toSet()
a corresponding downstream. The middle of that parameter HashMap::new
meaning is clear, and that is the return of Map implementation class which, if we wanted to change LinkedHashMap, write:
LinkedHashMap<Integer, Set<Goods>> goodsListMap = list.stream()
.collect(Collectors.groupingBy(Goods::getType, LinkedHashMap::new, Collectors.toSet()));
复制代码
This is heavy-duty use 3.
GroupingByConcurrent Collectors method is based on the heavy-duty 3 from the middle of the code changed ConcurrentHashMap::new
it.
public static <T, K>
Collector<T, ?, ConcurrentMap<K, List<T>>>
groupingByConcurrent(Function<? super T, ? extends K> classifier) {
return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList());
}复制代码
Collector parameters groupingBy method not only can toList (), toSet (), it also has a more flexible usage, before we are converted form, value is stored in a collection of objects, if you do not want so much property, only want the object to which the trade name ,, which means that we want , which is a key commodity type, value is the name of the collection of goods.Map
Map
This time Collectors.mapping()
comes in handy, we use the groupingBy(Function, Collector)
method, the second parameter passedCollectors.mapping()
Map<Integer, List<String>> goodsListMap =
list.stream()
.collect(
Collectors.groupingBy(
Goods::getType,
Collectors.mapping(Goods::getGoodsName, Collectors.toList())
)
);复制代码
Mapping () method takes two parameters, a first parameter specifies the property returns, the second parameter which specifies the return collection.
joining
The method of joining the elements can be spliced together Stream.
List<String> list = Arrays.asList("hello", "world");
String str = list.stream().collect(Collectors.joining());
System.out.println(str); // 打印:helloworld复制代码
You can also specify the delimiter:
List<String> list = Arrays.asList("hello", "world");
String str = list.stream().collect(Collectors.joining(","));
System.out.println(str); // 打印:hello,world复制代码
In addition, the String
class provides a join method, function is the same
String str2 = String.join(",", list);
System.out.println(str2);复制代码
maxBy&minBy
- maxBy: find the largest element in the Stream
@Data
@AllArgsConstructor
static class Goods {
private String goodsName;
private int price;
}
public static void main(String[] args) {
List<Goods> list = Arrays.asList(
new Goods("iphoneX", 4000)
, new Goods("mate30 pro", 5999)
, new Goods("redmek20", 2999)
);
Goods maxPriceGoods = list.stream()
.collect(
Collectors.maxBy(
Comparator.comparing(Goods::getPrice)
)
)
.orElse(null);
System.out.println("最贵的商品:" + maxPriceGoods);
}复制代码
The above example demonstrates find the most expensive commodity, Collectors.maxBy () method requires passing a comparison, we need to compare based on price goods.
Similarly, to find the cheapest goods simply maxBy
replace minBy
can.
partitioningBy
The method represents partitioningBy partition, it will be according to the conditions in the Stream element divided into two parts, and which were placed into a Map, the Map key is a Boolean type, the key storage element satisfies the condition part is true, false key is stored is not satisfied element conditions.
{
true -> 符合条件的元素
false -> 不符合条件的元素
}复制代码
The method consists of two overloaded methods partitioningBy composition
- Overload 1: partitioningBy (Predicate)
- 重载2:partitioningBy(Predicate, Collector)
Which will call the overloaded heavy-duty 1 2, and therefore eventually called method overloading 2, we look at the heavy load 1 method.
The following example of the type of product, the product is divided into categories of goods and non-mobile phones commodities.
@Data
@AllArgsConstructor
static class Goods {
private String goodsName;
// 类型,1:手机,2:电脑
private int type;
@Override
public String toString() {
return goodsName;
}
}
public static void main(String[] args) {
List<Goods> list = Arrays.asList(
new Goods("iphoneX", 1)
, new Goods("mate30 pro", 1)
, new Goods("thinkpad T400", 2)
, new Goods("macbook pro", 2)
);
// 手机归为一类,非手机商品归为一类
// true -> 手机类商品
// false -> 非手机类商品
Map<Boolean, List<Goods>> goodsMap = list.stream()
.collect(
Collectors.partitioningBy(goods -> goods.getType() == 1)
);
// 获取手机类商品
List<Goods> mobileGoods = goodsMap.get(true);
System.out.println(mobileGoods);
}复制代码
The second parameter partitioningBy (Predicate, Collector) method can be used to specify a set of elements used by default List store, if you want to use Set to store, write:
Map<Boolean, Set<Goods>> goodsMap = list.stream()
.collect(
Collectors.partitioningBy(
goods -> goods.getType() == 1
// 指定收集类型
, Collectors.toSet())
);复制代码
toList & toSet & toCollection
toList toSet and may convert the elements into Stream List, Set collection, which is more and more used two methods.
Stream<Goods> stream = Stream.of(
new Goods("iphoneX", 4000)
, new Goods("mate30 pro", 5999)
, new Goods("redmek20", 2999)
);
List<Goods> list = stream.collect(Collectors.toList());
Set<Goods> set = stream.collect(Collectors.toSet());复制代码
By default, toList returns ArrayList, toSet returns HashSet, if you want to return a collection of other types such as LinkedList, you can use toCollection
, it allows developers to specify their own set of needs what.
LinkedList<Goods> linkedList = stream.collect(Collectors.toCollection(LinkedList::new));复制代码
toConcurrentMap
Stream toConcurrentMap approach is to convert into ConcurrentMap, it is composed of three overloads
- Overload 1:
toConcurrentMap(Function keyMapper, Function valueMapper)
- Overload 2:
toConcurrentMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction)
- Heavy-duty 3:
toConcurrentMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction, Supplier
mapSupplier)
Overload 1 wherein calling overloaded 2, 3 overloaded call the overloaded 2, eventually implemented method overloads up to 3.
Look at the heavy-duty 1, two parameters
- keyMapper: key values specified in ConcurrentMap
- valueMapper: corresponding to the specified key value
The following example is the name of the product as a key, as a value price
List<Goods> list = Arrays.asList(
new Goods("iphoneX", 4000)
, new Goods("mate30 pro", 5999)
, new Goods("redmek20", 2999)
);
ConcurrentMap<String, Integer> goodsMap = list.stream()
.collect(
Collectors.toConcurrentMap(Goods::getGoodsName, Goods::getPrice)
);
System.out.println(goodsMap);复制代码
print:
{mate30 pro=5999, iphoneX=4000, redmek20=2999}复制代码
Note: This method requires the key can not be repeated, if there are duplicate key, it will throw IllegalStateException exception if there are duplicate key, use that overloads 2toConcurrentMap(Function, Function, BinaryOperator)
Then look at the heavy-duty 2: toConcurrentMap(Function, Function, BinaryOperator)
before this method two parameters with heavy-duty 1 as the third argument to deal with conflict situations key, allowing developers to select a value return value.
List<Goods> list = Arrays.asList(
new Goods("iphoneX", 4000)
, new Goods("mate30 pro", 5999)
, new Goods("mate30 pro", 6000) // 这里有两个冲突了
, new Goods("redmek20", 2999)
);
ConcurrentMap<String, Integer> goodsMap = list.stream()
.collect(
Collectors.toConcurrentMap(Goods::getGoodsName, Goods::getPrice, new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer price1, Integer price2) {
// 选择价格贵的返回
return Math.max(price1, price2);
}
})
);
System.out.println(goodsMap);复制代码
print:{mate30 pro=6000, iphoneX=4000, redmek20=2999}
This example mate30 pro repeat as key in BinaryOperator
, we chose a piece of data that the high price of return.
Finally, look overloaded 3, compared to the heavy-duty 2, the addition of a parameter Supplier
, which allows developers to specify a return one kindConcurrentMap
Call the overloaded overloaded 2 3, is used by default ConcurrentMap::new
.
Note: The fourth parameter must be a subclass of ConcurrentMap or ConcurrentMap
Section
Data in this chapter explain the Stream.collect
usage, as well as Collectors
the use of static methods of the class, the next article, we will explain in detail about reduce
the relevant usage.
Dry goods on a regular basis to share technology, learn together and progress together! Micro-channel public number: Under ape knocked on code