网站规划与网页设计总结,一元购网站建设多少钱,网站功能的介绍,网店推广引流[TOC] 0 Stream简介 家庭住址 #xff1a;java.util.stream.StreamT出生年月#xff1a;Java8问世的时候他就来到了世上主要技能#xff1a;那可以吹上三天三夜了…… 主要特征 不改变输入源中间的各种操作是lazy的(惰性求值、延迟操作)只有当开始消费流的时候… [TOC] 0 Stream简介 家庭住址 java.util.stream.StreamT出生年月Java8问世的时候他就来到了世上主要技能那可以吹上三天三夜了…… 主要特征 不改变输入源中间的各种操作是lazy的(惰性求值、延迟操作)只有当开始消费流的时候流才有意义隐式迭代……总体感觉Stream相当于一个进化版的Iterator。Java8源码里是这么注释的 A sequence of elements supporting sequential and parallel aggregate operations 可以方便的对集合进行遍历、过滤、映射、汇聚、切片等复杂操作。最终汇聚成一个新的Stream不改变原始数据。并且各种复杂的操作都是lazy的也就是说会尽可能的将所有的中间操作在最终的汇聚操作一次性完成。 比起传统的对象和数据的操作Stream更专注于对流的计算,和传说中的函数式编程有点类似。 他具体进化的多牛逼自己体验吧。 给一组输入数据: ListInteger list Arrays.asList(1, null, 3, 1, null, 4, 5, null, 2, 0); 求输入序列中非空奇数之和并且相同奇数算作同一个。 在lambda还在娘胎里的时候为了实现这个功能可能会这么做int s 0;
// 先放在Set里去重
SetInteger set new HashSet(list);
for (Integer i : set) {if (i ! null (i 1) 0) {s i;}
}
System.out.println(s); 当lambda和Stream双剑合璧之后int sum list.stream().filter(e - e ! null (e 1) 1).distinct().mapToInt(i - i).sum(); 1 获取Stream 从lambda的其他好基友那里获取Stream从1.8开始接口中也可以存在 default 修饰的方法了。 java.util.CollectionE 中有如下声明 public interface CollectionE extends IterableE {// 获取普通的流default StreamE stream() {return StreamSupport.stream(spliterator(), false);}// 获取并行流default StreamE parallelStream() {return StreamSupport.stream(spliterator(), true);}
} java.util.Arrays中有如下声明 public static T StreamT stream(T[] array) {return stream(array, 0, array.length);}public static IntStream stream(int[] array) {return stream(array, 0, array.length);}// 其他类似的方法不再一一列出 示例 ListString strs Arrays.asList(apache, spark);
StreamString stringStream strs.stream();IntStream intStream Arrays.stream(new int[] { 1, 25, 4, 2 }); 通过Stream接口获取StreamString stream Stream.of(hello, world);
StreamString stream2 Stream.of(haha);
StreamHouseInfo stream3 Stream.of(new HouseInfo[] { new HouseInfo(), new HouseInfo() });StreamInteger stream4 Stream.iterate(1, i - 2 * i 1);StreamDouble stream5 Stream.generate(() - Math.random()); 注意Stream.iterate()和 Stream.generate()生成的是无限流一般要手动limit 。 2 转换Stream 流过滤、流切片 这部分相对来说还算简单明了看个例子就够了 // 获取流
StreamString stream Stream.of(//null, apache, null, apache, apache, //github, docker, java, //hadoop, linux, spark, alifafa);stream// 去除null,保留包含a的字符串.filter(e - e ! null e.contains(a))//.distinct()// 去重,当然要有equals()和hashCode()方法支持了.limit(3)// 只取满足条件的前三个.forEach(System.out::println);// 消费流 map/flatMap Stream的map定义如下 R StreamR map(Function? super T, ? extends R mapper); 也就是说接收一个输入(T:当前正在迭代的元素)输出另一种类型(R)。 Stream.of(null, apache, null, apache, apache, //hadoop, linux, spark, alifafa)//.filter(e - e ! null e.length() 0)//.map(str - str.charAt(0))//取出第一个字符.forEach(System.out::println); sorted 排序也比较直观有两种 // 按照元素的Comparable接口的实现来排序
StreamT sorted();// 指定Comparator来自定义排序
StreamT sorted(Comparator? super T comparator); 示例: ListHouseInfo houseInfos Lists.newArrayList(//new HouseInfo(1, 恒大星级公寓, 100, 1), //new HouseInfo(2, 汇智湖畔, 999, 2), //new HouseInfo(3, 张江汤臣豪园, 100, 1), //new HouseInfo(4, 保利星苑, 23, 10), //new HouseInfo(5, 北顾小区, 66, 23), //new HouseInfo(6, 北杰公寓, null, 55), //new HouseInfo(7, 保利星苑, 77, 66), //new HouseInfo(8, 保利星苑, 111, 12)//
);houseInfos.stream().sorted((h1, h2) - {if (h1 null || h2 null)return 0;if (h1.getDistance() null || h2.getDistance() null)return 0;int ret h1.getDistance().compareTo(h2.getDistance());if (ret 0) {if (h1.getBrowseCount() null || h2.getBrowseCount() null)return 0;return h1.getBrowseCount().compareTo(h2.getBrowseCount());}return ret;
}); 3 终止/消费Stream 条件测试、初级统计操作 ListInteger list Arrays.asList(1, 2, 3, 4, 5);// 是不是所有元素都大于零
System.out.println(list.stream().allMatch(e - e 0));
// 是不是存在偶数
System.out.println(list.stream().anyMatch(e - (e 1) 0));
// 是不是都不小于零
System.out.println(list.stream().noneMatch(e - e 0));// 找出第一个大于等于4的元素
OptionalInteger optional list.stream().filter(e - e 4).findFirst();
// 如果存在的话,就执行ifPresent中指定的操作
optional.ifPresent(System.out::println);// 大于等于4的元素的个数
System.out.println(list.stream().filter(e - e 4).count());
// 获取最小的
System.out.println(list.stream().min(Integer::compareTo));
// 获取最大的
System.out.println(list.stream().max(Integer::compareTo));
// 先转换成IntStream,max就不需要比较器了
System.out.println(list.stream().mapToInt(i - i).max()); reduce 这个词不知道怎么翻译有人翻译为 规约 或 汇聚。 反正就是将经过一系列转换后的流中的数据最终收集起来收集的同时可能会反复 apply 某个 reduce函数。 reduce()方法有以下两个重载的变体 // 返回的不是Optional,因为正常情况下至少有参数identity可以保证返回值不会为null
T reduce(T identity, BinaryOperatorT accumulator);U U reduce(U identity,BiFunctionU, ? super T, U accumulator,BinaryOperatorU combiner); 示例 // 遍历元素反复apply (i,j)-ij的操作
Integer reduce Stream.iterate(1, i - i 1)//1,2,3,...,10,....limit(10)//.reduce(0, (i, j) - i j);//55OptionalInteger reduce2 Stream.iterate(1, i - i 1)//.limit(10)//.reduce((i, j) - i j); collect 该操作很好理解顾名思义就是将Stream中的元素collect到一个地方。 最常规(最不常用)的collect方法// 最牛逼的往往是最不常用的,毕竟这个方法理解起来太过复杂了
R R collect(SupplierR supplier,BiConsumerR, ? super T accumulator,BiConsumerR, R combiner);
// 至于这个方法的参数含义请看下面的例子 一个参数的版本R, A R collect(Collector? super T, A, R collector); Collector接口(他不是函数式接口没法使用lambda)的关键代码如下 public interface CollectorT, A, R {/****/SupplierA supplier();/*** */BiConsumerA, T accumulator();/*** */BinaryOperatorA combiner();/****/FunctionA, R finisher();/*** */SetCharacteristics characteristics();} 先来看一个关于三个参数的collect()方法的例子除非特殊情况不然我保证你看了之后这辈子都不想用它…… ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);
ArrayListInteger ret1 numbers.stream()//.map(i - i * 2)// 扩大两倍.collect(//() - new ArrayListInteger(), //参数1(list, e) - list.add(e), //参数2(list1, list2) - list1.addAll(list2)//参数3
);/**** pre* collect()方法的三个参数解释如下* 1. () - new ArrayListInteger() * 生成一个新的用来存储结果的集合* 2. (list, e) - list.add(e)* list是参数1中生成的新集合* e是Stream中正在被迭代的当前元素* 该参数的作用就是将元素添加到新生成的集合中* 3. (list1, list2) - list1.addAll(list2)* 合并集合* /pre***/ret1.forEach(System.out::println); 不使用lambda的时候等价的代码应该是这个样子的…… ListInteger ret3 numbers.stream()//.map(i - i * 2)// 扩大两倍.collect(new SupplierListInteger() {Overridepublic ListInteger get() {// 只是为了提供一个集合来存储元素return new ArrayList();}}, new BiConsumerListInteger, Integer() {Overridepublic void accept(ListInteger list, Integer e) {// 将当前元素添加至第一个参数返回的容器中list.add(e);}}, new BiConsumerListInteger, ListInteger() {Overridepublic void accept(ListInteger list1, ListInteger list2) {// 合并容器list1.addAll(list2);}});ret3.forEach(System.out::println); 是不是被恶心到了…… 同样的用Java调用spark的api的时候如果没有lambda的话比上面的代码还恶心…… 顺便打个免费的广告可以看看本大侠这篇使用各种版本实现的Spark的HelloWorld: http://blog.csdn.net/hylexus/...来证明一下有lambda的世界是有多么幸福…… 不过当你理解了三个参数的collect方法之后可以使用构造器引用和方法引用来使代码更简洁 ArrayListInteger ret2 numbers.stream()//.map(i - i * 2)// 扩大两倍.collect(//ArrayList::new, //List::add, //List::addAll//
);ret2.forEach(System.out::println); Collectors工具的使用(高级统计操作) 上面的三个和一个参数的collect()方法都异常复杂最常用的还是一个参数的版本。但是那个Collector自己实现的话还是很恶心。 还好常用的Collect操作对应的Collector都在java.util.stream.Collectors 中提供了。很强大的工具…… 以下示例都是对该list的操作 ListHouseInfo houseInfos Lists.newArrayList(//new HouseInfo(1, 恒大星级公寓, 100, 1), // 小区ID小区名浏览数距离new HouseInfo(2, 汇智湖畔, 999, 2), //new HouseInfo(3, 张江汤臣豪园, 100, 1), //new HouseInfo(4, 保利星苑, 111, 10), //new HouseInfo(5, 北顾小区, 66, 23), //new HouseInfo(6, 北杰公寓, 77, 55), //new HouseInfo(7, 保利星苑, 77, 66), //new HouseInfo(8, 保利星苑, 111, 12)//
); 好了开始装逼之旅 ^_^ …… 提取小区名// 获取所有小区名放到list中
ListString ret1 houseInfos.stream().map(HouseInfo::getHouseName).collect(Collectors.toList());
ret1.forEach(System.out::println);// 获取所有的小区名放到set中去重
// 当然也可先distinct()再collect到List中
SetString ret2 houseInfos.stream().map(HouseInfo::getHouseName).collect(Collectors.toSet());
ret2.forEach(System.out::println);// 将所有的小区名用_^_连接起来
// 恒大星级公寓_^_汇智湖畔_^_张江汤臣豪园_^_保利星苑_^_北顾小区_^_北杰公寓_^_保利星苑_^_保利星苑
String names houseInfos.stream().map(HouseInfo::getHouseName).collect(Collectors.joining(_^_));
System.out.println(names);// 指定集合类型为ArrayList
ArrayListString collect houseInfos.stream().map(HouseInfo::getHouseName).collect(Collectors.toCollection(ArrayList::new)); 最值// 获取浏览数最高的小区
OptionalHouseInfo ret3 houseInfos.stream()//.filter(h - h.getBrowseCount() ! null)// 过滤掉浏览数为空的.collect(Collectors.maxBy((h1, h2) - Integer.compare(h1.getBrowseCount(), h2.getBrowseCount())));
System.out.println(ret3.get());// 获取最高浏览数
OptionalInteger ret4 houseInfos.stream()//.filter(h - h.getBrowseCount() ! null)// 去掉浏览数为空的.map(HouseInfo::getBrowseCount)// 取出浏览数.collect(Collectors.maxBy(Integer::compare));// 方法引用比较浏览数
System.out.println(ret4.get()); 总数、总和// 获取总数
// 其实这个操作直接用houseInfos.size()就可以了此处仅为演示语法
Long total houseInfos.stream().collect(Collectors.counting());
System.out.println(total);// 浏览数总和
Integer ret5 houseInfos.stream()//.filter(h - h.getBrowseCount() ! null)// 过滤掉浏览数为空的.collect(Collectors.summingInt(HouseInfo::getBrowseCount));
System.out.println(ret5);// 浏览数总和
Integer ret6 houseInfos.stream()//.filter(h - h.getBrowseCount() ! null)// 过滤掉浏览数为空的.map(HouseInfo::getBrowseCount).collect(Collectors.summingInt(i - i));
System.out.println(ret6);// 浏览数总和
int ret7 houseInfos.stream()//.filter(h - h.getBrowseCount() ! null)// 过滤掉浏览数为空的.mapToInt(HouseInfo::getBrowseCount)// 先转换为IntStream后直接用其sum()方法.sum();
System.out.println(ret7); 均值// 浏览数平均值
Double ret8 houseInfos.stream()//.filter(h - h.getBrowseCount() ! null)// 过滤掉浏览数为空的.collect(Collectors.averagingDouble(HouseInfo::getBrowseCount));
System.out.println(ret8);// 浏览数平均值
OptionalDouble ret9 houseInfos.stream()//.filter(h - h.getBrowseCount() ! null)// 过滤掉浏览数为空的.mapToDouble(HouseInfo::getBrowseCount)// 先转换为DoubleStream后直接用其average()方法.average();
System.out.println(ret9.getAsDouble()); 统计信息// 获取统计信息
DoubleSummaryStatistics statistics houseInfos.stream()//.filter(h - h.getBrowseCount() ! null).collect(Collectors.summarizingDouble(HouseInfo::getBrowseCount));
System.out.println(avg: statistics.getAverage());
System.out.println(max: statistics.getMax());
System.out.println(sum: statistics.getSum()); 分组// 按浏览数分组
MapInteger, ListHouseInfo ret10 houseInfos.stream()//.filter(h - h.getBrowseCount() ! null)// 过滤掉浏览数为空的.collect(Collectors.groupingBy(HouseInfo::getBrowseCount));
ret10.forEach((count, house) - {System.out.println(BrowseCount: count house);
});// 多级分组
// 先按浏览数分组,二级分组用距离分组
MapInteger, MapString, ListHouseInfo ret11 houseInfos.stream()//.filter(h - h.getBrowseCount() ! null h.getDistance() ! null)//.collect(Collectors.groupingBy(HouseInfo::getBrowseCount,Collectors.groupingBy((HouseInfo h) - {if (h.getDistance() 10)return 较近;else if (h.getDistance() 20)return 近;return 较远;})));//结果大概长这样
ret11.forEach((count, v) - {System.out.println(浏览数: count);v.forEach((desc, houses) - {System.out.println(\t desc);houses.forEach(h - System.out.println(\t\t h));});
});
/***** pre* 浏览数:66较远HouseInfo [houseId5, houseName北顾小区, browseCount66, distance23]浏览数:100较近HouseInfo [houseId1, houseName恒大星级公寓, browseCount100, distance1]HouseInfo [houseId3, houseName张江汤臣豪园, browseCount100, distance1]浏览数:999较近HouseInfo [houseId2, houseName汇智湖畔, browseCount999, distance2]浏览数:77较远HouseInfo [houseId6, houseName北杰公寓, browseCount77, distance55]HouseInfo [houseId7, houseName保利星苑, browseCount77, distance66]浏览数:111近HouseInfo [houseId8, houseName保利星苑, browseCount111, distance12]较近HouseInfo [houseId4, houseName保利星苑, browseCount111, distance10]* * /pre* ****/ 分区// 按距离分区(两部分)
MapBoolean, ListHouseInfo ret12 houseInfos.stream()//.filter(h - h.getDistance() ! null)//.collect(Collectors.partitioningBy(h - h.getDistance() 20));
/***** pre* 较远HouseInfo [houseId5, houseName北顾小区, browseCount66, distance23]HouseInfo [houseId6, houseName北杰公寓, browseCount77, distance55]HouseInfo [houseId7, houseName保利星苑, browseCount77, distance66]较近HouseInfo [houseId1, houseName恒大星级公寓, browseCount100, distance1]HouseInfo [houseId2, houseName汇智湖畔, browseCount999, distance2]HouseInfo [houseId3, houseName张江汤臣豪园, browseCount100, distance1]HouseInfo [houseId4, houseName保利星苑, browseCount111, distance10]HouseInfo [houseId8, houseName保利星苑, browseCount111, distance12]* * /pre****/
ret12.forEach((t, houses) - {System.out.println(t ? 较近 : 较远);houses.forEach(h - System.out.println(\t\t h));
});MapBoolean, MapBoolean, ListHouseInfo ret13 houseInfos.stream()//.filter(h - h.getDistance() ! null)//.collect(Collectors.partitioningBy(h - h.getDistance() 20,Collectors.partitioningBy(h - h.getBrowseCount() 70))
);/****** pre* 较远浏览较少HouseInfo [houseId5, houseName北顾小区, browseCount66, distance23]浏览较多HouseInfo [houseId6, houseName北杰公寓, browseCount77, distance55]HouseInfo [houseId7, houseName保利星苑, browseCount77, distance66]较近浏览较少浏览较多HouseInfo [houseId1, houseName恒大星级公寓, browseCount100, distance1]HouseInfo [houseId2, houseName汇智湖畔, browseCount999, distance2]HouseInfo [houseId3, houseName张江汤臣豪园, browseCount100, distance1]HouseInfo [houseId4, houseName保利星苑, browseCount111, distance10]HouseInfo [houseId8, houseName保利星苑, browseCount111, distance12]* /pre****/ret13.forEach((less, value) - {System.out.println(less ? 较近 : 较远);value.forEach((moreCount, houses) - {System.out.println(moreCount ? \t浏览较多 : \t浏览较少);houses.forEach(h - System.out.println(\t\t h));});
});