Jdk8 Stream的API使用 流式编程
Java8的Stream就是典型的例子,Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
例子:
List<Integer> numbers = new ArrayList<>();
numbers.add(3);
numbers.add(4);
numbers.add(8);
numbers.add(16);
numbers.add(19);
numbers.add(27);
numbers.add(23);
numbers.add(99);
numbers.add(15);
numbers.add(32);
numbers.add(5);
numbers.add(232);
numbers.add(56);
int count = 0;
for(Integer i:numbers){if(i>20){count++;}
}
System.out.println("count:"+count);
如上遍历的代码转换成使用Stream的API来实现如下:long count = numbers.stream().filter(i->i>20).count();
System.out.println("count:"+count);
正常的遍历用Stream一行就可以实现了。
下面是一个使用了Stream API实现的流程图。
转换成Java代码就是
Integer transactionsIds =roomList.stream().filter(b -> b.getLength() == 10).sorted((x,y) -> x.getHigh() - y.getHigh()).mapToInt(Room::getWidth).sum();
创建Stream
Arrays.stream()
当在日常编程中面对的是一个数组,也可以使用Arrays.stream()方法来使用Stream
Integer[] array = new Integer[]{3,4,8,16,19,27,23,99,76,232,33,96};
long count = Arrays.stream(array).filter(i->i>20).count();
Stream.of()
当面对数组时除了可以使用Arrays.stream()方法外,还可以使用Stream将需要的数组转成Stream。这个方法不但支持传入数组,将数组转成Stream,也支持传入多个参数,将参数最终转成Stream
Integer[] array = new Integer[]{3,4,8,16,19,27,23,99,76,232,33,96};
long count = Stream.of(array).filter(i->i>20).count();
long sum = Stream.of(12,77,59,3,654).filter(i->i>20).mapToInt(Integer::intValue).sum();
System.out.println("count:"+count+",sum:"+sum);
其实Stream.of()也是调用的Stream.of()方法来实现的。
Stream.generate()
Stream接口有两个用来创建无限Stream的静态方法。generate()方法接受一个参数函数,可以使用类似如下代码来创建一个你需要的Stream。
Stream<String> stream = Stream.generate(() -> "test").limit(10);
String[] strArr = stream.toArray(String[]::new);
System.out.println(Arrays.toString(strArr));
运行结果
[test, test, test, test, test, test, test, test, test, test]
Stream.iterate()
Stream接口的另一用来创建无限Stream的静态方法就是iterate()方法。iterate()方法也是接受一个参数函数,可以用类似如下代码来创建一个你需要的Stream。
> Stream<BigInteger> bigIntStream = Stream.iterate(BigInteger.ZERO, n ->
> n.add(BigInteger.TEN)).limit(10); BigInteger[] bigIntArr =
> bigIntStream.toArray(BigInteger[]::new);
> System.out.println(Arrays.toString(bigIntArr));
运行结果
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
Collection.stream()
这个就是最常见的Stream了。因为Collection是Java中集合接口的父接口,Java中的集合都继承或实现了此接口。所以Java中的集合都可以使用此方法来创建一个Stream;
/*** @see Set* @see List* @see Map* @see SortedSet* @see SortedMap* @see HashSet* @see TreeSet* @see ArrayList* @see LinkedList* @see Vector* @see Collections* @see Arrays* @see AbstractCollection* @since 1.2*/public interface Collection<E> extends Iterable<E> {/*** Returns a sequential {@code Stream} with this collection as its source.** <p>This method should be overridden when the {@link #spliterator()}* method cannot return a spliterator that is {@code IMMUTABLE},* {@code CONCURRENT}, or <em>late-binding</em>. (See {@link #spliterator()}* for details.)** @implSpec* The default implementation creates a sequential {@code Stream} from the* collection's {@code Spliterator}.** @return a sequential {@code Stream} over the elements in this collection* @since 1.8*/default Stream<E> stream() {return StreamSupport.stream(spliterator(), false);}}
例子
List<Integer> numbers = new ArrayList<>();
numbers.add(3);
numbers.add(4);
numbers.add(8);
numbers.add(16);
numbers.stream().forEach(number->{System.out.println(number);
});
StreamSupport.stream()
通过查看Collection.stream()的方法,我们可以看出来,Colleciton.stream()其实是调用了StreamSupport.stream()来实现的。所以我们也可以使用StreamSupport.stream()来创建一个Stream。当我们面对的是一个迭代器的时候,使用StreamSupport.stream()就可以创建一个Stream。第一个参数是传入一个迭代器,第二个参数是true代表使用并行来进行处理。false代表串行来处理Stream。
List<Integer> numbers = new ArrayList<>();
numbers.add(3);
numbers.add(4);
numbers.add(8);
numbers.add(16);
numbers.add(19);
numbers.add(27);
numbers.add(23);
Spliterator<Integer> integers = numbers.spliterator();
StreamSupport.stream(integers,false).forEach(number->{System.out.println(number);
});
流的转换filter方法
从名字上就能看出来,这是一个Stream的过滤转换,此方法会生成一个新的流,其中包含符合某个特定条件的所有元素。
List<Integer> integerList = Lists.newArrayList();
integerList.add(15);
integerList.add(32);
integerList.add(5);
integerList.add(232);
integerList.add(56);
List<Integer> after = integerList.stream().filter(i->i>50).collect(Collectors.toList());
System.out.println(after);
运行结果:
[232, 56]
map方法
map方法指对一个流中的值进行某种形式的转换。需要传递给它一个转换的函数作为参数。
List<Integer> integerList = Lists.newArrayList();
integerList.add(15);
integerList.add(32);
integerList.add(5);
integerList.add(232);
integerList.add(56);
//将Integer类型转换成String类型
List<String> afterString = integerList.stream().map(i->String.valueOf(i)).collect(Collectors.toList());
System.out.println(afterString);
flatMap方法
上面用map方法进行流转换的时候,是对每个元素应用一个函数,并将返回的值收集到一个新的流中。但是如果有一个函数,它返回的不是一个值,而是一个包含多个值的流。但是你需要的是一个包含多个流中的元素的集合。
例如
List<Integer> oneList = Lists.newArrayList(),
twoList = Lists.newArrayList();
oneList.add(34);
oneList.add(23);
oneList.add(87);twoList.add(29);
twoList.add(48);
twoList.add(92);
Map<String,List<Integer>> testMap = Maps.newHashMap();
testMap.put("1",oneList);
testMap.put("2",twoList);
//返回的是一个流的集合,但是我需要的是List<Integer>这样一个集合
List<Stream<Integer>> testList = testMap.values().stream().map(number->number.stream()).collect(Collectors.toList());
这个时候就应该使用flatMap将多个流进行合并,然后再收集到一个集合中。
List<Integer> testList = testMap.values().stream().flatMap(number->number.stream()).collect(Collectors.toList());
limit方法和skip方法
limit(n)方法会返回一个包含n个元素的新的流(若总长小于n则返回原始流)。
List<Integer> myList = Lists.newArrayList();
myList.add(1);
myList.add(2);
myList.add(3);
myList.add(4);
myList.add(5);
myList.add(6);
List<Integer> afterLimit = myList.stream().limit(4).collect(Collectors.toList());
System.out.println("afterLimit:"+afterLimit);
skip(n)方法正好相反,它会丢弃掉前面的n个元素。
List<Integer> afterSkip = myList.stream().skip(4).collect(Collectors.toList());
System.out.println("afterSkip:"+afterSkip);
运行结果:
afterLimit:[1, 2, 3, 4] afterSkip:[5, 6]
用limit和skip方法一起使用就可以实现日常的分页功能:List<Integer> pageList = myList.stream().skip(pageNumber*pageSize).limit(pageSize).collect(Collectors.toList());
distinct方法和sorted方法
上面介绍的流的转换方法都是无状态的。即从一个已经转换的流中取某个元素时,结果并不依赖于之前的元素。除此之外还有两个方法在转换流时是需要依赖于之前流中的元素的。一个是distinct方法一个是sorted方法。
distinct方法会根据原始流中的元素返回一个具有相同顺序、去除了重复元素的流,这个操作显然是需要记住之前读取的元素。
List<Integer> myTestList = Lists.newArrayList();
myTestList.add(10);
myTestList.add(39);
myTestList.add(10);
myTestList.add(78);
myTestList.add(10);
List<Integer> distinctList = myTestList.stream().distinct().collect(Collectors.toList());
System.out.println("distinctList:"+distinctList);
运行结果:
distinctList:[10, 39, 78]
sorted方法是需要遍历整个流的,并在产生任何元素之前对它进行排序。因为有可能排序后集合的第一个元素会在未排序集合的最后一位。
List<Integer> myTestList = Lists.newArrayList();
myTestList.add(39);
myTestList.add(78);
myTestList.add(10);
myTestList.add(22);
myTestList.add(56);
List<Integer> sortList = myTestList.stream().sorted(Integer::compareTo).collect(Collectors.toList());
System.out.println("sortList:"+sortList);
运行结果:
sortList:[10, 22, 39, 56, 78]
聚合操作
前面已经介绍了流的创建和转换,下面介绍流的聚合,聚合是指将流汇聚为一个值,以便在程序中使用。聚合方法都是终止操作。
max方法和min方法
在前面的代码例子中使用的count方法和sum方法都属于流从聚合方法。还有两个聚合方法是max方法和min方法,分别返回流中最大值和最小值。
List<Integer> hearList = Lists.newArrayList();
hearList.add(15);
hearList.add(32);
hearList.add(5);
hearList.add(232);
hearList.add(56);
hearList.add(29);
hearList.add(94);
Integer maxItem = hearList.stream().max(Integer::compareTo).get();
Integer minItem = hearList.stream().min(Integer::compareTo).get();
System.out.println("max:"+maxItem+",min:"+minItem);
运行结果:
max:232,min:5
findFirst方法
findFirst方法返回非空集合中的第一个值,它通常与filter方法结合起来使用。
List<Integer> hearList = Lists.newArrayList();
hearList.add(15);
hearList.add(32);
hearList.add(5);
hearList.add(232);
hearList.add(56);
hearList.add(29);
hearList.add(104);
Integer first = hearList.stream().filter(i->i>100).findFirst().get();
findAny方法
findAny方法可以在集合中只要找到任何一个所匹配的元素,就返回,此方法在对流并行执行时十分有效(任何片段中发现第一个匹配元素都会结束计算,串行流中和findFirst返回一样)。
Integer anyItem = hearList.parallelStream().filter(i->i>100).findAny().get();
anyMatch方法
anyMatch方法可以判定集合中是否还有匹配的元素。返回结果是一个boolean类型值。
boolean isHas = hearList.parallelStream().anyMatch(i->i>100);
allMatch方法和noneMatch方法
allMatch方法和noneMatch方法,分别在所有元素匹配和没有元素匹配时返回true。
boolean allHas = hearList.parallelStream().allMatch(i->i>100); boolean
noHas = hearList.parallelStream().noneMatch(i->i>100);
虽然这些方法总是会检查整个流,但是仍然可以通过并行执行来提高速度
reduce方法
reduce方法是将流中的元素进行进一步计算的方法。
List<Integer> hearList = Lists.newArrayList();
hearList.add(15);
hearList.add(32);
hearList.add(5);
hearList.add(232);
hearList.add(56);
hearList.add(29);
hearList.add(104);
//求和
Integer sum = hearList.stream().reduce((x,y)->x+y).get();
System.out.println("sum:"+sum);
//简化一下,求和
sum = hearList.stream().reduce(Integer::sum).get();
System.out.println("sum:"+sum);
//含有初始标识的,求和
sum = hearList.stream().reduce(0,(x,y)->x+y);
System.out.println("sum:"+sum);
//对元素的长度进行求和( (total,y)->total+y.toString().length(),类似于一个累加器,会被重复调用)
sum = hearList.stream().reduce(0,(total,y)->total+y.toString().length(),(total1,total2)->total1+total2);
System.out.println("sum:"+sum);
//简化一下,对元素长度进行求和。
sum = hearList.stream().map(Objects::toString).mapToInt(String::length).sum();
System.out.println("sum:"+sum);
运行结果
sum:473 sum:473 sum:473 sum:15 sum:15
收集结果
当处理完流之后,通常是想查看一下结果,而不是将他们聚合为一个值。Collectorts类为我们提供了常用的收集类的各个工厂方法。
收集到集合
例如前面的例子用的要将一个流收集到一个List中,只需要这样写就可以。
List<Integer> thereList = hereList.stream().collect(Collectors.toList());
收集到Set中可以这样用
Set<Integer> thereSet = hereList.stream().collect(Collectors.toSet());
收集到Set时,控制Set的类型,可以这样。
TreeSet<Integer> treeSet = hereList.stream().collect(Collectors.toCollection(TreeSet::new));
joining拼接
将字流中的字符串连接并收集起来。
String resultString = stringList.stream().collect(Collectors.joining());
在将流中的字符串连接并收集起来时,想在元素中介添加分隔符,传递个joining方法即可。
String resultString = stringList.stream().collect(Collectors.joining(","));
当流中的元素不是字符串时,需要先将流转成字符串流再进行拼接。
String hereResultString = hereList.stream().map(String::valueOf).collect(Collectors.joining(","));
收集聚合
分别收集流的总和、平均值、最大值或者最小值。
List<Integer> hereList = Lists.newArrayList();
hereList.add(15);
hereList.add(32);
hereList.add(5);
hereList.add(232);
hereList.add(56);
hereList.add(29);
hereList.add(104);
//总和、平均值,最大值,最小值
int sum = hereList.stream().collect(Collectors.summingInt(Integer::intValue));
Double ave = hereList.stream().collect(Collectors.averagingInt(Integer::intValue));
Integer max = hereList.stream().collect(Collectors.maxBy(Integer::compare)).get();
Integer min = hereList.stream().collect(Collectors.minBy(Integer::compare)).get();
System.out.println("sum:"+sum+",ave:"+ave+",max:"+max+",min:"+min);
运行结果:
sum:473,ave:67.57142857142857,max:232,min:5
一次性收集流中的结果,聚合为一个总和,平均值,最大值或最小值的对象。
IntSummaryStatistics summaryStatistics = hereList.stream().collect(Collectors.summarizingInt(Integer::intValue));System.out.println(summaryStatistics);
运行结果:
IntSummaryStatistics{count=7, sum=473, min=5, average=67.571429,
max=232}
将结果集收集到Map
当我们希望将集合中的元素收集到Map中时,可以
使用Collectors.toMap方法。
这个方法有两个参数,用来生成Map的key和value。
例如将一个Room对象的high作为键width作为值
Map<Integer,Integer> hwMap = roomList.stream().collect(Collectors.toMap(Room::getHigh, Room::getWidth));
但是通常还是以具体元素作为值的情况多,可以使用
Function.identity()
来获取实际元素。
Map<Integer,Room> roomMap = roomList.stream().collect(Collectors.toMap(Room::getHigh, Function.identity()));
如果多个元素拥有相同的键,在收集结果时会抛出java.lang.IllegalStateException异常。可以使用第三个参数来解决,第三个参数用来确定当出现键冲突时,该如何处理结果,如果当出现键冲突时只保留一个并且是保留已经存在的值时,就是如下方式。
Map<Integer,Room> rMap = roomList.stream().collect(Collectors.toMap(Room::getHigh, Function.identity(),(nowValue,newValue)->nowValue));
如果想指定生成的Map类型,则还需要第三个参数。TreeMap<Integer,Room> roomTreeMap = roomList.stream().collect(Collectors.toMap(Room::getHigh, Function.identity(),(nowValue,newValue)->newValue,TreeMap::new));
注意:每个toMap方法,都会有一个对应的toConCurrentMap方法,用来生成一个并发Map。
分组分片
在一个集合中,对具有相同特性的值进行分组是一个很常见的功能,在Stream的API中也提供了相应的方法。
分组
还是上面的例子,将一个Room对象集合按照高度分组。
List<Room> roomList = Lists.newArrayList(
new Room(11,23,56),
new Room(11,84,48),
new Room(22,46,112),
new Room(22,75,62),
new Room(22,56,75),
new Room(33,92,224));Map<Integer,List<Room>> groupMap = roomList.stream().collect(Collectors.groupingBy(Room::getHigh));
System.out.println("groupMap:"+groupMap);
运行结果:
groupMap:{33=[Room(high=33, width=92, length=224)], 22=[Room(high=22,
width=46, length=112), Room(high=22, width=75, length=62),
Room(high=22, width=56, length=75)], 11=[Room(high=11, width=23,
length=56), Room(high=11, width=84, length=48)]}分片
当分类函数是一个返回布尔值的函数时,流元素会被分为两组列表:一组是返回true的元素集合,另一组是返回false的元素集合。这种情况适用partitoningBy方法会比groupingBy更有效率。
例如我们将房间集合分为两组,一组是高度为22的房间,另一组是其他房间。
Map<Boolean,List<Room>> partitionMap = roomList.stream().collect(Collectors.partitioningBy(room->room.getHigh()==22));
运行结果:
partitionMap:{false=[Room(high=11, width=23, length=56), Room(high=11,
width=84, length=48), Room(high=33, width=92, length=224)],
true=[Room(high=22, width=46, length=112), Room(high=22, width=75,
length=62), Room(high=22, width=56, length=75)]}
扩展功能
下面要介绍的这些方法功能,无论是groupingBy方法还是partitioningBy方法都是支持的。
counting方法会返回收集元素的总个数。
Map<Integer,Long> countMap = roomList.stream().collect(Collectors.groupingBy(Room::getHigh,Collectors.counting()));
summing(Int|Long|Double)方法接受一个取值函数作为参数,来计算总和。
Map<Integer,Integer> sumMap = roomList.stream().collect(Collectors.groupingBy(Room::getHigh,Collectors.summingInt(Room::getWidth)));
maxBy方法和minBy方法
接受比较器作为参数来计算最大值和最小值。
取出分组中宽度最大和最小的房间。
Map<Integer, Optional<Room>> maxMap = roomList.stream().collect(Collectors.groupingBy(Room::getHigh,Collectors.maxBy(Comparator.comparing(Room::getWidth))));
Map<Integer, Optional<Room>> minMap = roomList.stream().collect(Collectors.groupingBy(Room::getHigh,Collectors.minBy(Comparator.comparing(Room::getWidth))));System.out.println("maxMap:"+ JSON.toJSONString(maxMap));
System.out.println("minMap:"+JSON.toJSONString(minMap));
运行结果:
maxMap:{33:{“high”:33,“length”:224,“width”:92},22:{“high”:22,“length”:62,“width”:75},11:{“high”:11,“length”:48,“width”:84}}
minMap:{33:{“high”:33,“length”:224,“width”:92},22:{“high”:22,“length”:112,“width”:46},11:{“high”:11,“length”:56,“width”:23}}
mapping方法会将结果应用到另一个收集器上。
取出分组中宽度最大的房间的宽度。
Map<Integer, Optional<Integer>> collect = roomList.stream().collect(Collectors.groupingBy(Room::getHigh,Collectors.mapping(Room::getWidth,Collectors.maxBy(Comparator.comparing(Integer::valueOf)))));System.out.println("collect:"+JSON.toJSONString(collect));
运行结果:
collect:{33:92,22:75,11:84}
无论groupingBy或是mapping函数,如果返回类型是int、long、double都可以将元素收集到一个summarystatistics对象中,然后从每组的summarystatistics对象中取出函数值的总和、平均值、总数、最大值和最小值。
Map<Integer,IntSummaryStatistics> summaryStatisticsMap =
roomList.stream()
.collect(Collectors.groupingBy(Room::getHigh,
Collectors.summarizingInt(Room::getWidth)));System.out.println(“summaryStatisticsMap:”+summaryStatisticsMap);
运行结果:summaryStatisticsMap:{33=IntSummaryStatistics{count=1, sum=92, min=92,
average=92.000000, max=92}, 22=IntSummaryStatistics{count=3, sum=177,
min=46, average=59.000000, max=75}, 11=IntSummaryStatistics{count=2,
sum=107, min=23, average=53.500000, max=84}}多级分组
上面的例子我们都是按一个条件进行的一级分组,其实groupingBy是支持多级分组的。
例如第一级我们将房间按照高度分组,第二级按照宽度分组。
Map<Integer,Map<Integer,List<Room>>> multistageMap = roomList.stream().collect(Collectors.groupingBy(Room::getHigh,Collectors.groupingBy(Room::getWidth)));System.out.println("multistageMap:"+JSON.toJSONString(multistageMap));
运行结果:
{
“11”: {
“23”: [
{“high”: 11,“length”: 56,“width”: 23}
],
“84”: [
{“high”: 11,“length”: 48,“width”: 84}
]
},
“22”: {
“46”: [
{“high”: 22,“length”: 112,“width”: 46}
],
“56”: [
{“high”: 22,“length”: 75,“width”: 56}
],
“75”: [
{“high”: 22,“length”: 62,“width”: 75}
]
},
“33”: {
“92”: [
{“high”: 33,“length”: 224,“width”: 92}
]
} }
并行流
Stream的建立,使得并行计算变得容易,但是并行流在使用的时候也是需要注意的。
首先,必须是一个并行流,只要在终止方法执行时,流处于并行模式,那么所有的流操作就都会并行执行。
Stream.of(roomList).parallel();
parallel方法可以将任意的串行流转换为一个并行流。
其次要确保传递给并行流操作的函数是线程安全的。
int[] words = new int[23];
Stream.of(roomList).parallel().forEach(s->{if(s.size()<10){words[s.size()]++;}
});
上面这个例子中的代码就是错误的,传递给并行流的操作并不是线程安全的。可以改为AtomicInteger的对象数组来作为计数器。
我们使在处理集合数据量较大的时候才能体现出并行流的优势,并且目的是为了在保证线程安全的情况下,提升效率,利用多核CPU的资源。
小扩展
使用Stream的API时,在遍历或处理流的过程中当引用外部变量的时候会默认的将变量当成fianl变量来处理。所以有些同学就会觉得在遍历的过程中取不出来集合的索引。其实可以换一种思想可以只遍历集合索引,然后在遍历中取值。
IntStream.range(0,roomList.size()).forEach(i->{System.out.println(roomList.get(i));
});
@Testvoid streamTest() {List<Integer> numbers = new ArrayList<>();numbers.add(3);numbers.add(4);numbers.add(8);numbers.add(16);numbers.add(19);numbers.add(27);numbers.add(23);numbers.add(99);numbers.add(15);numbers.add(32);numbers.add(5);numbers.add(232);numbers.add(56);//计算long count = numbers.stream().filter(i -> i > 20).count();System.out.println("计算count:" + count);//判断是否 有匹配的boolean anyMatch = numbers.stream().anyMatch(i -> i > 100);System.out.println("判断是否有匹配的anyMatch;" + anyMatch);//判断全部是否有匹配的boolean allMatch = numbers.stream().allMatch(i -> i == 100);System.out.println("判断是否有匹配的allMatch;" + anyMatch);//最大的的Integer compare1 = Stream.of(2, 1, 4, 5, 3).max(Integer::compare).get();System.out.println("最大的的compare;" + compare1);//排序numbers.sort((x, y) -> {return Integer.compare(x, y);});//迭代Iterator<Integer> iterator = numbers.iterator();while (iterator.hasNext()) {Integer next = iterator.next();System.out.print(next + ",");}System.out.println("=====");//数组Integer[] array = new Integer[]{3, 4, 8, 16, 19, 27, 23, 99, 76, 232, 33, 96};long count1 = Arrays.stream(array).filter(i -> i > 22).count();System.out.println("数组Arrays.stream(array).filter(i ->i>22 ).count();" + count1);//sum累计 .mapToInt(Integer::intValue).sum()long sum = Stream.of(array).filter(i -> i > 50).mapToInt(Integer::intValue).sum();System.out.println("sum累计 .mapToInt(Integer::intValue).sum(); " + sum);//生成Stream<String> streamlimit = Stream.generate(() -> "Hello").limit(10);String[] strings = streamlimit.toArray(String[]::new);System.out.println("生成Stream.generate(() -> \"Hello\").limit(10);" + Arrays.toString(strings));//Stream<BigInteger> bigIntStream = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.TEN)).limit(10);BigInteger[] bigIntArr = bigIntStream.toArray(BigInteger[]::new);System.out.println(Arrays.toString(bigIntArr));//遍历numbers.stream().forEach((number) -> System.out.print(number + "."));System.out.println("迭代numbers.stream().forEach((number)-> System.out.print(number+\".\"));");//StreamSupport.stream(spliterator(), false)Spliterator<Integer> spliterator = numbers.spliterator();StreamSupport.stream(spliterator, false).forEach(nu -> System.out.print(nu + "。"));System.out.println("StreamSupport.stream(spliterator(), false串行)");//转换流List<Integer> collect = numbers.stream().filter(j -> j > 50).collect(Collectors.toList());System.out.println(".collect(Collectors.toList()); " + collect);//map个流中的值进行某种形式的转换 将Integer类型转换成String类型numbers.stream().map(i -> String.valueOf(i)).collect(Collectors.toList()).forEach(num -> System.out.print(num + ";"));System.out.println("map个流中的值进行某种形式的转换.map(i->String.valueOf(i)).collect(Collectors.toList()).forEach");//如果有一个函数,它返回的不是一个值,而是一个包含多个值的流。List<Integer> oneList = Lists.newArrayList(),twoList = Lists.newArrayList();oneList.add(34);oneList.add(23);oneList.add(87);twoList.add(29);twoList.add(48);twoList.add(92);Map<String, List<Integer>> testMap = Maps.newHashMap();testMap.put("1", oneList);testMap.put("2", twoList);
//返回的是一个流的集合,但是我需要的是List<Integer>这样一个集合Collection<List<Integer>> values = testMap.values();values.stream().map(number -> number.stream()).collect(Collectors.toList()).forEach(str -> str.forEach(i -> System.out.print(i + "=")));System.out.println("");//flatMaptestMap.values().stream().flatMap(num -> num.stream()).collect(Collectors.toSet()).forEach(se -> System.out.print(se));//limit方法 返回一个包含n个元素的新的流// skip方法 返回一个n个外元素的新的流System.out.println("limit方法 返回一个包含n个元素的新的流");numbers.stream().limit(8).collect(Collectors.toList()).forEach(i -> System.out.print(i + "/"));System.out.println("skip方法 返回一个n个外元素的新的流");numbers.stream().skip(8).forEach(i -> System.out.print("#" + i));//用limit和skip方法一起使用就可以实现日常的分页功能:System.out.println("用limit和skip方法分页");numbers.stream().skip(2 * 3).limit(3).forEach(i -> System.out.println("P" + i));//distinct去重 排序List<Integer> numbers2 = new ArrayList<>();numbers2.add(23);numbers2.add(4);numbers2.add(8);numbers2.add(4);numbers2.add(66);numbers2.add(8);numbers2.add(55);System.out.println("distinct去重 原顺序");numbers2.stream().distinct().collect(Collectors.toList()).forEach(i -> System.out.print("-" + i));System.out.println("");System.out.println(" sorted 排序 不去重");numbers2.stream().sorted().collect(Collectors.toList()).forEach(i -> System.out.print("-" + i));System.out.println("");System.out.println("去重 排序");numbers2.stream().distinct().sorted().collect(Collectors.toList()).forEach(i-> System.out.print("^"+i));System.out.println("");System.out.println("findFirst 返回第一个");System.err.println(numbers2.stream().findFirst().get());System.err.println(numbers2.stream().filter(i->i>50).findFirst().get());//findAny方法可以在集合中只要找到任何一个所匹配的元素System.err.println(numbers2.parallelStream().filter(i->i>50).findAny().get());//anyMatch方法可以判定集合中是否还有匹配的元素System.err.println("anyMatch方法可以判定集合中是否还有匹配的元素--"+numbers2.parallelStream().anyMatch(i -> i == 66));Integer sum2 = numbers2.stream().reduce(Integer::sum).get();Integer sum3 = numbers2.stream().reduce((x,y)->x+y).get();System.out.println("求和:reduce(Integer::sum).get()=="+sum2+"--"+sum3);int sum4 = numbers2.stream().map(Object::toString).mapToInt(String::length).sum();System.out.println("strig长度:"+sum4);String resultString = numbers2.stream().map(Object::toString).collect(Collectors.joining());String resultStr = numbers2.stream().map(Object::toString).collect(Collectors.joining("*"));System.out.println(resultString+"____"+resultStr);//收集聚合 求和 平均 最大 最小Integer summing = numbers2.stream().collect(Collectors.summingInt(Integer::intValue));Double ave = numbers2.stream().collect(Collectors.averagingInt(Integer::intValue));Integer maxby = numbers2.stream().collect(Collectors.maxBy(Integer::compare)).get();Integer minby = numbers2.stream().collect(Collectors.minBy(Integer::compare)).get();System.out.println("sum:"+summing+"ave:"+ave+"max:"+maxby+"min:"+minby);//一次性收集流中的结果,聚合为一个总和,平均值,最大值或最小值的对象。IntSummaryStatistics collect1 = numbers2.stream().collect(Collectors.summarizingInt(Integer::intValue));System.out.println("一次性收集:"+collect1);//Map将集合中的元素收集到Map中时,List<User> userList = Lists.newArrayList(new User(1,"2","BB"),new User(2,"3","BB"),new User(3,"4","BB"),new User(4,"5","224"));new User(4,"5","224");Map<Integer, String> map = userList.stream().collect(Collectors.toMap(User::getId, User::getName));map.entrySet().forEach(i-> System.out.print(i));HashMap<Integer, User> hashMap = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(), (nowValue, newValue) -> newValue, HashMap::new));System.out.println("");hashMap.entrySet().forEach(i-> System.out.println(i));}
Jdk8 Stream的API使用 流式编程相关推荐
- Lambda表达式和Stream流式编程
写在前面 IDEA都默认是jdk11了,我这还写着jdk8的新特性呢,惭愧惭愧.其实在学校的时候,基本没咋用过Lambda表达式和Stream流式编程,但是在实习的时候,发现公司的代码好多这样写的,没 ...
- Java Stream流式编程
流式编程Stream 一.简介 流式 API 从 Java8 开始引入,支持链式书写. 流只能消费一次,不能被两次消费(两次最终操作) 流在管道中流通,在节点被处理. 流[无存储],流不是一种数据结构 ...
- Java8新特性之Stream流式编程
特地感谢鲁班大叔的分享,原学习地址:Java8 Stream流式编程爱 撸码就是快,流式编程好 代码传家宝 以下是学习过程整理的笔记 1.简介 Stream 流处理,首先要澄清的是 java8 中的 ...
- RxJava2.x是一个非常棒的流式编程,采用的观察者模式思想,事件的产生者产生事间之后发送给绑定的接受者,接受顺序与发送顺序一致.但是 是独立于RxJava1.x存在,本文讲解RxJava2.x的简
RxJava2.x是一个非常棒的流式编程,采用的观察者模式思想,事件的产生者产生事间之后发送给绑定的接受者,接受顺序与发送顺序一致.但是 是独立于RxJava1.x存在,本文讲解RxJava2.x的简 ...
- java中Lambda+流式编程讲解(心得篇)
首先举一个例子来说明,我们要在一群人里面刷选一些,首先自己写一个Person类: package 任务十三__流式计算.公司;import java.util.Objects;/*** @author ...
- 【Java】流式编程学习笔记
文章目录 一.流简介 二.创建流 2.1 由值创建流:of 2.2 由列表创建流:stream 2.3 由 Builder 创建流:build 2.4 由文件生成流:lines 2.5 由函数生成流 ...
- ReactiveX流式编程—从xstream讲起
ReactiveX流式编程 ReactiveX来自微软,它是一种针对异步数据流的编程.简单来说,它将一切数据,包括HTTP请求,DOM事件或者普通数据等包装成流的形式,然后用强大丰富的操作符对流进行处 ...
- 20190827 On Java8 第十四章 流式编程
第十四章 流式编程 流的一个核心好处是,它使得程序更加短小并且更易理解.当 Lambda 表达式和方法引用(method references)和流一起使用的时候会让人感觉自成一体.流使得 Java ...
- Flink系列之Flink 流式编程模式总结
title: Flink系列 一.Flink 流式编程模式总结 1.1 基础总结 官网: https://flink.apache.org/ Apache Flink® - Stateful Comp ...
最新文章
- jquery.raty评星插件
- 给你两个经纬度,计算他们之间的距离
- 数据库性能调优之后,进一步的验证和分析
- 让你觉得破坏了封装性的扩展方法
- SAP Fiori Launchpad tile点击之后的跳转链接是如何解析出来的
- “拯救网站运维经理赵明”有奖方案征集启事
- Python18行代码做出来这样有点浪漫,又有点极客的“内涵”图
- 版本控制软件Visual Source safe使用小结 (配合上文)
- Maven构建项目 — 知识点梳理
- ActiveMq工作笔记003---SpringBoot集成ActiveMq_随时更新
- SpringCloud工作笔记038---spring cloud微服务权限认证_终于确定下来大体的思想了
- Js实现文字水平滚动
- [分享]屏幕取色工具
- SCOM 2012 RC 升级到 SCOM 2012 RTM 手记
- (转)比特币基金难产 区块链基金成首发
- C语言——冒泡排序法,数组
- 拟合和统计中的检验参数
- clover删除多余引导_[转载]EFI引导如何去掉多余的这个clover启动项
- java期末大作业:记事本
- 延迟队列DelayQueue研究