三个主要功能
java.util.stream.Collector
它的实现类
java.util.stream.Collectors
Apple
public class Apple {
private String color;
private long weight;
public Apple() {
}
public Apple(String color, long weight) {
this.color = color;
this.weight = weight;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public long getWeight() {
return weight;
}
public void setWeight(long weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Apple{" +
"color='" + color + '\'' +
", weight=" + weight +
'}';
}
}
聚合
public static void main(String[] args) {
List list = Arrays.asList(
new Apple("green", 150),
new Apple("yellow", 120),
new Apple("green", 170));
List greenList = list.stream().filter(a -> a.getColor().equals("green")).collect(Collectors.toList());
Optional.of(greenList).ifPresent(System.out::println);
//[Apple{color='green', weight=150}, Apple{color='green', weight=170}]
}
根据颜色分组
/**
* 按颜色分组
* @param apples
* @return
*/
private static Map> groupByNomal(List apples){
Map> map = new HashMap<>();
for (Apple apple : apples) {
List list = map.get(apple.getColor());
if(list==null){
list=new ArrayList<>();
map.put(apple.getColor(),list);
}
list.add(apple);
}
return map;
}
Optional.of(groupByNomal(list)).ifPresent(System.out::println);
//{green=[Apple{color='green', weight=150}, Apple{color='green', weight=170}],
// yellow=[Apple{color='yellow', weight=120}]}
private static Map> groupByFunction(List apples) {
Map> map = new HashMap<>();
apples.parallelStream().forEach(a -> {
List colorList = Optional.ofNullable(map.get(a.getColor())).orElseGet(() -> {
List list = new ArrayList<>();
map.put(a.getColor(), list);
return list;
});
colorList.add(a);
});
// map=null; (Variable used in lambda expression should be final or effectively final)
return map;
}
lambda中使用外层的变量,不能在lamdba表达式中修改其值,外层变量可以不是final类型的,但是绝对不可以在lambda表达式中修改外层变量的值。(Variable used in lambda expression should be final or effectively final)
Optional.ofNullable(groupByFunction(list)).ifPresent(System.out::println);
private static Map> groupByCollector(List apples) {
return apples.parallelStream().collect(groupingBy(Apple::getColor));
}
Optional.ofNullable(groupByCollector(list)).ifPresent(System.out::println);
很快捷
公共类
Dish
public class Dish {
private final String name;
private final boolean vegetarian;
private final int calories;
private final Type type;
public Dish(String name, boolean vegetarian, int calories, Type type) {
this.name = name;
this.vegetarian = vegetarian;
this.calories = calories;
this.type = type;
}
public String getName() {
return name;
}
public boolean isVegetarian() {
return vegetarian;
}
public int getCalories() {
return calories;
}
public Type getType() {
return type;
}
public enum Type {MEAT, FISH, OTHER}
@Override
public String toString() {
return "Dish{" +
"name='" + name + '\'' +
", vegetarian=" + vegetarian +
", calories=" + calories +
", type=" + type +
'}';
}
}
初始化数据
public static List menu = Arrays.asList(
new Dish("pork", false, 800, Dish.Type.MEAT),
new Dish("beef", false, 700, Dish.Type.MEAT),
new Dish("chicken", false, 400, Dish.Type.MEAT),
new Dish("french fries", true, 530, Dish.Type.OTHER),
new Dish("rice", true, 350, Dish.Type.OTHER),
new Dish("season fruit", true, 120, Dish.Type.OTHER),
new Dish("pizza", true, 550, Dish.Type.OTHER),
new Dish("prawns", false, 300, Dish.Type.FISH),
new Dish("salmon", false, 450, Dish.Type.FISH));
private static void testAveragingDouble() {
System.out.println("testAveragingDouble");
//求 平均数 返回 double
Optional.ofNullable(menu.stream().collect(Collectors.averagingDouble(Dish::getCalories)))
.ifPresent(System.out::println);
}
private static void testAveragingInt() {
System.out.println("testAveragingInt");
Optional.ofNullable(menu.stream().collect(Collectors.averagingInt(Dish::getCalories)))
.ifPresent(System.out::println);
}
private static void testAveragingLong() {
System.out.println("testAveragingLong");
Optional.ofNullable(menu.stream().collect(Collectors.averagingLong(Dish::getCalories)))
.ifPresent(System.out::println);
}
test
public static void main(String[] args) {
testAveragingDouble();
testAveragingInt();
testAveragingLong();
}
java.util.stream.Collectors#averagingDouble 源码
public static Collector
averagingDouble(ToDoubleFunction super T> mapper) { //ToDoubleFunction返回double类型
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the number of values seen.
*/
return new CollectorImpl<>(
() -> new double[4],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); a[2]++; a[3]+= mapper.applyAsDouble(t);},
(a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
CH_NOID);
}
java.util.function.ToDoubleFunction
给任意一个参数返回一个double类型数据
@FunctionalInterface
public interface ToDoubleFunction {
/**
* Applies this function to the given argument.
*
* @param value the function argument
* @return the function result
*/
double applyAsDouble(T value);
}
private static void testCollectingAndThen() {
System.out.println("testCollectingAndThen");
String collect = menu.stream().collect(Collectors.collectingAndThen(
Collectors.averagingInt(Dish::getCalories), a -> "The Average Calories is->" + a));
Optional.ofNullable(collect).ifPresent(System.out::println);
}
返回的东西会被修改怎么办
Collections::unmodifiableList
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
实际上就是 将返回的结果 用 Collections.unmodifiableList(list);这个方法包装后再返回
List dishes = Collections.unmodifiableList(list);
private static void testCollectingAndThen() {
System.out.println("testCollectingAndThen");
String collect = menu.stream().collect(Collectors.collectingAndThen(
Collectors.averagingInt(Dish::getCalories), a -> "The Average Calories is->" + a));
Optional.ofNullable(collect).ifPresent(System.out::println);
List list = menu.stream().filter(d -> d.getType().equals(Dish.Type.MEAT))
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
list.add(new Dish("", false, 100, Dish.Type.OTHER));
System.out.println(list);
}
private static void testCounting() {
System.out.println("testCounting");
Optional.of(menu.stream().collect(
Collectors.counting()
)).ifPresent(System.out::println);//9
}
private static void testGroupingByFunction() {
System.out.println("testGroupingByFunction");
Map> collect = menu.stream().collect(
Collectors.groupingBy(Dish::getType)
);
Optional.of(collect).ifPresent(System.out::println);
}
private static void testGroupingByFunctionAndCollector() {
System.out.println("testGroupingByFunctionAndCollector");
Map collect = menu.stream().collect(
Collectors.groupingBy(
Dish::getType,
Collectors.counting()
));
Optional.of(collect).ifPresent(System.out::println);
}
private static void testGroupingByFunctionAndCollector() {
System.out.println("testGroupingByFunctionAndCollector");
Map collect = menu.stream().collect(
Collectors.groupingBy(
Dish::getType,
Collectors.averagingInt(Dish::getCalories)
));
Optional.of(collect).ifPresent(System.out::println);
}
private static void testGroupingByFunctionAndSupplierAndCollector() {
System.out.println("testGroupingByFunctionAndSupplierAndCollector");
Map map = menu.stream().collect(
Collectors.groupingBy(Dish::getType,
TreeMap::new,
Collectors.averagingInt(Dish::getCalories)
));
Optional.of(map.getClass()).ifPresent(System.out::println);
Optional.of(map).ifPresent(System.out::println);
}
private static void testSummarizingInt() {
System.out.println("testSummarizingInt");
IntSummaryStatistics result = menu.stream().collect(
Collectors.summarizingInt(Dish::getCalories)
);
Optional.of(result).ifPresent(System.out::println);
}