Java8的流特性-常用操作(例)
2018-02-03 17:18
447 查看
- 描述:
- 流的一些常用操作
- 转自:https://lw900925.github.io/java/java8-stream-api.html
public class StreamMethods { /** * 流的过滤 * 大部分流操作的结果仍然是一个流,所以我们可以链式调用 */ public void testStreamFilter() { List<Integer> integers = new ArrayList<>(); integers.addAll(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8)); //使用流类库 integers = integers.stream().filter(i -> i > 5).collect(Collectors.toList()); System.out.println(integers); } /** * 流的映射 * 类似于SQL中的select,可以将一组元素转换成另一种元素。 * 下面的例子将一组整数转换为平方。这是一个简单的例子,实际场合中常常需要将一组对象流转换为另一组对象。 */ public void testStreamMap() { List<Integer> integers = Stream.of(1, 2, 3, 4) .map(i -> i * i) .collect(Collectors.toList()); System.out.println(integers); } /** * 流的平整映射 * 有时候需要将多个流的结果合并为一个流,这时候需要使用平整映射。 */ public void testStreamFlatMap() { List<Integer> integers = Stream.of(Arrays.asList(1, 2, 3, 4), Arrays.asList(5, 6)) .flatMap(n -> n.stream()) .collect(Collectors.toList()); System.out.println(integers); } /** * 流求最大或最小值 */ public void testStreamMaxOrMin() { int min = Stream.of(1, 23, 4, 50, 8888) .min(Comparator.comparingInt(i -> i)) .get(); int max = Stream.of(0, 1, 2, 5, 89, 465, 45, 666, 8888) .max(Comparator.comparingInt(i -> i)).get(); System.out.println(String.format("max:%d,min:%d", max, min)); } /** * TODO 不太懂这个接口 流的通用迭代 reduce */ public void testStreamReduce() { int sum = Stream.of(1, 2, 3, 4, 5) .reduce((acc, e) -> acc + e).get(); System.out.println(String.format("sum:%d", sum)); int product = Stream.of(1, 2, 3, 4, 5) .reduce(1, (acc, e) -> acc * e); System.out.println(String.format("product:%d", product)); } /** * 流的一些谓词特性 * allMatch:当所有条件满足时返回true * anyMatch:只要有一个元素满足就返回true * noneMatch:当没有元素返回时返回true * distinct:去掉重复的元素 * limit:保留流的前几个元素 * skip:跳过前几个元素而获取之后的所有元素 */ public void testStreamPredicate() { boolean allMatch = Stream.of(1, 2, 3, 4, 5).allMatch(i -> i > 3); System.out.println("allMatch: " + allMatch); boolean anyEqual = Stream.of(1, 2, 3, 4, 5).anyMatch(i -> i >= 2); System.out.println("anyMatch: " + anyEqual); boolean noneEqual = Stream.of(1, 2, 3, 4, 5).noneMatch(i -> i < 0); System.out.println("noMatch: " + noneEqual); List<Integer> list = Stream.of(1, 2, 3, 4, 2, 2, 4, 3, 1, 2, 4, 3, 1, 2) .distinct() .collect(Collectors.toList()); System.out.println(list); String list1 = Stream.of(1, 2, 3, 4, 5, 6) .limit(3) .map(String::valueOf) .collect(Collectors.joining(", ", "[", "]")); System.out.println(list1); String list2 = Stream.of(1, 2, 3, 4, 5, 6) .skip(3) .map(String::valueOf) .collect(Collectors.joining(", ", "[", "]")); System.out.println(list2); } /** * 基本类型流 * 由于Java存在一个基本类型装箱拆箱的过程,所以会有性能开销。 * 为了避免这些开销,流类库针对常见的基本类型int、long、double做了特殊处理, * 为它们单独准备了一些类和方法。 * 注意:对于一些方法也有基本类型的版本,可以将一个对象流转换为对应的基本类型, * 这些方法的命名规则是方法名+To+基本类型。如果需要处理大量数据的基本类型流, * 可以考虑使用这些方法。 */ public void testStreamPrimitiveType() { IntStream intStream = IntStream.of(1, 2, 3, 4, 5); LongStream longStream = LongStream.of(1, 2, 3, 4, 5); DoubleStream doubleStream = DoubleStream.of(10, 2.0, 3.0); int sum = Stream.of(1, 2, 3, 4, 5) .mapToInt(i -> i) .reduce(0, (acc, e) -> acc + e); //.sum(); System.out.println("sum :" + sum); } /** * 流的收集器(collect()方法) * 使用流类库的最后一步就是将流转换为我们需要的集合了,这就需要用到收集器。 * 收集数据的最后一步需要调用collect方法,它的参数是java.util.stream.Collector类的静态方法。 * 听起来是不是有点奇怪,实际上,接受的是这些方法的返回值。 * 例如toList()方法实际上是这样的,返回的是Collector对象,然后由collect方法处理,获取最后的集 * 合。 * 源代码示例 * public static <T>Collector<T, ?, List<T>> toList() { * return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add, * (left, right) -> { left.addAll(right); return left; }, * CH_ID); * } */ /** * 通过收集器获得流的集合 */ public void testGetStreamCollections(){ List<Integer> integers = Stream.of(1,2,3,4,5) .collect(Collectors.toList()); System.out.println("list: "+integers); Set<Integer> set = Stream.of(1,2,2,3,4,5) .collect(Collectors.toSet()); System.out.println("set: "+set); //使用自己希望的集合(可以构造成map集合或concurrentMap集合) ArrayList<Integer> integerArrayList = Stream.of(1,2,3) .collect(Collectors.toCollection(ArrayList::new)); System.out.println("integerArrayList: "+integerArrayList); } /** * 通过收集器获取流的值 * 收集器不仅可以获得集合,还可以由流获取一个值, * 这可以通过调用maxBy、minBy、averageXXX和summingXXX方法来实现 */ public void testGetStreamValue(){ int max = Stream.of(1,2,3,4) .collect(Collectors.maxBy(Comparator.comparing(i->i))) .get(); int min = Stream.of(1,2,3,4) .collect(Collectors.minBy(Comparator.comparing(i->i))) .get(); double average = Stream.of(1,2,3,4) .collect(Collectors.averagingInt(Integer::intValue)); int sum = Stream.of(1,2,3,4) .collect(Collectors.summingInt(i->i)); System.out.println( String.format("max:%d,min:%d,average:%f,sum:%d", max, min, average, sum)); /** * 有时候需要将流的数据组合为一个字符串,这需要joining收集器,它的三个参数分别是分隔符、前缀和后缀。 * 当然由于它需要字符序列,所以这里还需要用map方法将整数流转换为字符串流。 */ String string = Stream.of(1,2,3,4,5) .map(String::valueOf) .collect(Collectors.joining(", ","[","]")); System.out.println("string :"+string); /** * 还有一个简单的收集器,作用就是计数,需要注意的是计数返回的结果是long类型就行了。 * 这个收集器的主要作用是和其他收集器一起完成复杂的功能。 */ Long count = Stream.of(1,2,3,4,5,6,7,8) .collect(Collectors.counting()); // .count(); System.out.println("count: "+count); } /** * 流的数据分块 */ public void testStreamDataPartition() { Map<Boolean, List<Integer>> map = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) .collect(Collectors.partitioningBy(i -> i % 2 == 0)); System.out.println("map: " + map); } /** * 流的数据分组 * 类似于SQL中的group by语句。下面的例子将流按照数组个位数分为好几组 */ public void testDataGrouping() { Map<Integer, List<Integer>> map = Stream.of(21, 32, 43, 54, 11, 33, 22) .collect(Collectors.groupingBy(i -> i % 10)); System.out.println("map: "+map); } /** * 流的组合收集器 * 如果问题比较复杂,还可以将多个收集器组合起来使用,一些收集器有重载的版本,支持第二个收集器, * 可以用来实现这个功能。就拿前面那个数据分组的例子来说,这次我不仅要分组, * 而且只需要每组的十位数字,那么就可以这样写。 * groupingBy的第二个参数可以使用mapping收集器,mapping这里的作用和流操作的map类似, * 将流再次进行映射,然后收集结果作为最后Map的键值对。 */ public void testGroupCollect(){ //按个位数字进行分组,然后只获取十位上的数字 Map<Integer, List<Integer>> map = Stream.of(21, 32, 43, 54, 11, 33, 22) .collect(Collectors.groupingBy(i -> i % 10, Collectors.mapping(i -> i / 10,Collectors.toList()))); System.out.println("map: "+map); //按个位数字分组,然后然后求各组的和 Map<Integer,Integer> map1 = Stream.of(21,32,43,54,11,33,22) .collect(Collectors.groupingBy(i->i%10,Collectors.summingInt(i->i))); System.out.println("map1: "+map1); } /** * 关于流的其它特性 */ public void testOther(){ /** * * 所有的流操作都是惰性的,也就是说直到最后调用收集器的时候,整个流操作才开始进行。 * 在这之前,你的流操作只不过类似于SQL的执行计划,这时候还没有真正执行程序。所以下面的代码什么都不会输出。 */ Stream.of(1,2,3,4,5) .filter(i->i>1) .filter(i->{ System.out.println("i: "+i); return i<=3; }); /** * 如果进行了很多流操作,流类库会不会对流进行多次迭代,导致程序速度很慢呢? * 这个担心也是多余的,流类库经过优化,会保证迭代以最少的次数进行。 * 所以下面的代码输出结果是122334455,这说明流只迭代了一次。 */ List<Integer> integers = Stream.of(1, 2, 3, 4, 5) .filter(i -> { System.out.print(i); return i > 1; }) .filter(i -> { System.out.print(i); return i <= 3; }) .collect(Collectors.toList()); System.out.println(integers); } /** * 流的循环 */ public void testForLoop(){ /** * 流的循环,相当于for循环 */ IntStream.range(0, 3) .forEach(i -> System.out.print(i)); } /** * 流的数据并行化 * 需要注意并不是说并行化之后,速度就一定会比串行化快, * 这需要根据当前系统、机器、执行的数据流大小来进行综合评估。 * ArrayList这类容器就比较容易并行化,而HashMap并行化就比较困难。 */ public void testStreamParallel(){ List<Integer> integers = IntStream.range(1, 101) .parallel() .filter(i -> i % 2 == 0) .boxed() .collect(Collectors.toList()); System.out.println("integers :"+integers); } }
相关文章推荐
- java8新特性(1)-基于stream集合分组(包含stream对集合常用操作的功能)
- Java日期操作常用方法(转自 csdn)
- JAVA程序员-常用LINUX基础操作收集
- Java中按照行读取和写入文件 日志常用操作 解决中文乱码问题
- JAVA对数字证书的常用操作
- java中关于时间日期操作的常用函数
- java中数组的常用操作
- 有关java IO 常用操作复习
- JAVA对数字证书的常用操作
- java中关于时间日期操作的常用函数
- java中关于时间日期操作的常用函数
- java中关于时间日期操作的常用函数
- java 数组操作1.5后新特性--可变参数以及foreach使用
- java 常用日期时间操作函数
- java Jbutton常用操作
- java操作数组的常用类
- java操作文件常用方式
- java中关于时间日期操作的常用函数
- 收藏:java中关于时间日期操作的常用函数
- java中关于时间日期操作的常用函数