接上一篇流的中间操作
Java8-Stream流Intermediate中间操作详解
约简操作:
1、max(Comparator) 获取最大值
int [] arr = {1,1,2,3,4,4,5};
OptionalInt max = Arrays.stream(arr).max();
System.out.println(max.orElse(0));// 5
2、min(Comparator) 获取最小值
OptionalInt min = Arrays.stream(arr).min();
System.out.println(min.orElse(0));// 1
3、count() 获取总数
long count = Arrays.stream(arr).count();
System.out.println(count);// 7
4、findFirst() 返回第一个元素
// 获取比3大的第一个数
OptionalInt first = Arrays.stream(arr).filter(o -> o > 3).findFirst();
System.out.println(first.orElse(0));// 4
5、findAny() 返回任意元素
// 获取任一个比1大的数
OptionalInt any = Arrays.stream(arr).filter(o -> o > 1).findAny();
System.out.println(any.orElse(0));// 2
6、anyMatch(Predicate) 任意元素匹配时返回true
String [] str = {"python","php","java"};
boolean anyMatch = Arrays.stream(str).anyMatch(s -> s.startsWith("p"));
System.out.println(anyMatch);// true
boolean anyMatch2 = Arrays.stream(str).anyMatch(s -> s.startsWith("a"));
System.out.println(anyMatch2);// false
7、allMatch(Predicate) 所有元素匹配时返回true
String [] str = {"python","php","hello"};
boolean allMatch = Arrays.stream(str).allMatch(s -> s.contains("h"));
System.out.println(allMatch);// true
boolean allMatch3 = Arrays.stream(str).allMatch(s -> s.contains("p"));
System.out.println(allMatch3);// false
8、noneMatch(Predicate) 没有元素匹配时返回true
boolean noneMatch = Arrays.stream(str).noneMatch(s -> s.contains("h"));
System.out.println(noneMatch);// false
boolean noneMatch2 = Arrays.stream(str).noneMatch(s -> s.contains("p"));
System.out.println(noneMatch2);// false
boolean noneMatch3 = Arrays.stream(str).noneMatch(s -> s.contains("a"));
System.out.println(noneMatch3);// true
通俗点讲reduce就是把stream中的元素给组合起来。至于怎么组合起来:它需要我们首先提供一个起始种子,然后依照某种运算规则使其与stream的第一个元素发生关系产生一个新的种子,这个新的种子再紧接着与stream的第二个元素发生关系产生又一个新的种子,就这样依次递归执行,最后产生的结果就是reduce的最终产出
9、reduce(fun)
从流中计算某个值,接受一个二元函数作为累积器,从前两个元素开始持续应用它,累积器的中间结果作为第一个参数,流元素作为第二个参数
比如
//我们对一组数据求和
int [] arr = {1,3,5,7,9};
// 没有起始值时返回Optional类型
OptionalInt maxValue = Arrays.stream(arr).reduce(Integer::sum);
System.out.println(maxValue.orElse(0));// 25
nt sum = Arrays.stream(arr).sum();
System.out.println(sum);//25
10、reduce(a, fun) a为种子,作为累积器的起点
int [] arr = {1,3,5,7,9};
// 有起始值时返回具体类型
int reduce = Arrays.stream(arr).reduce(100, Integer::sum);
System.out.println(reduce);// 100 + 25
**11、reduce(a, fun1, fun2) **
reduce有三个参数时,第三个参数combiner主要是使用在并行计算的场景下;如果Stream是非并行时,第三个参数实际上是不生效的。因此针对这个方法的分析需要分并行与非并行两个场景。
List<Integer> integers = Arrays.asList(1000, 1000, 1000);
Integer reduce1 = integers.stream().reduce(-500, (a, b) -> a + b, (a, b) -> a + b);
System.out.println(reduce1);// 2500
这里串行时先把每个元素的和求出再与我们的种子相加,这里第三个参数实际是没什么用的。但是在并行流的情况下
Integer reduce2 = integers.parallelStream().reduce(-500, (a, b) -> a + b, (a, b) -> a + b);
System.out.println(reduce2);// 1500
结果是1500,好比我一个卡,同时存钱1000,取钱500,遍历完后余额就是1500,等同于以下写法
Optional<Integer> reduce3 = integers.stream().map(o -> -500 + o).reduce((a, b) -> a + b);
System.out.println(reduce3.get());
1、List 转换为 list set map
@Test
public void testCollector(){
List<Dish> mean = 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)
);
// 1.List
List<String> names = mean.stream().map(Dish::getName).collect(Collectors.toList());
// 2.List -> Set
Set<String> set = mean.stream().map(Dish::getName).collect(Collectors.toSet());
// 转map,需要指定key和value,Function.identity()表示当前的Emp对象本身
Map<String, Dish> dishMap = mean.stream().collect(Collectors.toMap(Dish::getName, Function.identity()));
}
// 计算元素个数
Long count = mean.stream().collect(Collectors.counting());
// 求和
IntSummaryStatistics intSummaryStatistics = mean.stream().collect(Collectors.summarizingInt(Dish::getCalories));
DoubleSummaryStatistics doubleSummaryStatistics = mean.stream().collect(Collectors.summarizingDouble(Dish::getCalories));
LongSummaryStatistics longSummaryStatistics = mean.stream().collect(Collectors.summarizingLong(Dish::getCalories));
// 平均值
Double aveCalor = mean.stream().collect(Collectors.averagingInt(Dish::getCalories));
// 综合处理
System.out.println(intSummaryStatistics.getMax());// 800
System.out.println(intSummaryStatistics.getMin());// 120
System.out.println(intSummaryStatistics.getAverage());// 466.66
System.out.println(intSummaryStatistics.getCount());// 9
System.out.println(intSummaryStatistics.getSum());// 4200
// 处理字符串集合 增加分隔符 前缀 后缀等等
String nameStr = mean.stream().map(Dish::getName).collect(Collectors.joining());
String nameStr1 = mean.stream().map(Dish::getName).collect(Collectors.joining("|"));
String nameStr2 = mean.stream().map(Dish::getName).collect(Collectors.joining("-","start","end"));
System.out.println(nameStr);// porkbeefchickenfrench friesriceseason fruitpizzaprawnssalmon
System.out.println(nameStr1);// pork|beef|chicken|french fries|rice|season fruit|pizza|prawns|salmon
System.out.println(nameStr2);// startpork-beef-chicken-french fries-rice-season fruit-pizza-prawns-salmonend
toMap(Function keyMapper,Function valueMapper) keyMapper: 该Funtion用来生成Key valueMapper:该Funtion用来生成value
转换map时可能有几个问题
当我们的key有重复时:
// 当我们的key 有重复时
List<Integer> integers = Arrays.asList(1, 1, 3, 4, 5);
Map<Integer, Integer> integerMap = integers.stream().collect(Collectors.toMap(k -> k, v -> v));
System.out.println(integerMap);//java.lang.IllegalStateException: Duplicate key 1
当我们的value值为null时
// 当value值有null时
List<Integer> integers = Arrays.asList(1, null, 3, 4, 5);
Map<Integer, Integer> integerMap = integers.stream().collect(Collectors.toMap(k -> k, v -> v));
System.out.println(integerMap);//java.lang.NullPointerException
对于重复的key 我们可以用三个参数的map
List<Integer> integers = Arrays.asList(1, 1, 3, 4, 5);
Map<Integer, Integer> integerMap = integers.stream().collect(Collectors.toMap(k -> k, v -> v,(k1,k2)->k1));
System.out.println(integerMap);//{1=1, 3=3, 4=4, 5=5}
map还有四个参数的方法,我们可以指定返回的map类型:
List<Integer> integers = Arrays.asList(1, 1, 3, 4, 5);
Map<Integer, Integer> integerMap = integers.stream().collect(Collectors.toMap(k -> k, v -> v,(k1,k2)->k1,LinkedHashMap::new));
System.out.println(integerMap);//{1=1, 3=3, 4=4, 5=5}
groupBy 分组
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 3, 4, 5, 2);
Map<Boolean, List<Integer>> collect = integers.stream().collect(Collectors.groupingBy(i -> i > 2));
System.out.println(collect);// {false=[1, 2, 2], true=[3, 4, 5, 6, 3, 4, 5]}
多条件分组
Map<Boolean, Map<Boolean, List<Integer>>> collect = integers.stream()
.collect(Collectors.groupingBy(i -> i > 2, Collectors.groupingBy(j -> j < 5)));
System.out.println(collect);// {false={true=[1, 2, 2]}, true={false=[5, 6, 5], true=[3, 4, 3, 4]}}
分组统计
// 统计大于2 的个数
Map<Boolean, Long> collect1 = integers.stream().collect(Collectors.groupingBy(i -> i > 2, Collectors.counting()));
System.out.println(collect1);//{false=3, true=7}
分区:partitioningBy
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 3, 4, 5, 2);
Map<Boolean, List<Integer>> collect2 = integers.stream().collect(Collectors.partitioningBy(i -> i > 4));
System.out.println(collect2);// {false=[1, 2, 3, 4, 3, 4, 2], true=[5, 6, 5]}
后续再补充…