个人转载仅作为笔记使用,如有任何问题可以到原文链接探讨,原文连接为:https://www.cnblogs.com/jimoer/p/10995574.html

前言

这次想介绍一下Java Stream的API使用,最近在做一个新的项目,然后终于可以从老项目的祖传代码坑里跳出来了。项目用公司自己的框架搭建完成后,我就想着把JDK版本也升级一下吧(之前的项目,最高就能用JDK7),但是后来发现公司的项目部署打包平台最高只支持到JDK8。那好吧,既然就支持到JDK8,也能满足日常需求了(要啥自行车),升级到JDK8后,在搭建完项目架构后,就开始写一些基础逻辑。其中就用到了一些JDK8的Stream。但是我的同事在看我的代码的时候表示看不懂。确实,这个我也承认,Lambda表达式虽然代码简洁,但是不会用的人会觉得它的可读性不是太好。所以这次就结合自己使用经验来介绍一下Java Stream的一些功能。

从遍历到Stream操作

Oracle 公司于 2014 年 3 月 18 日发布 Java 8,Java8主要是在原来面向对象的基础上增加了函数式编程的能力。这样就出现了在Java中使用Lambda表达式,将一个函数作为方法的参数来进行传递。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);

运行结果:

count:6

如上遍历的代码转换成使用Stream的API来实现如下:

long count = numbers.stream().filter(i->i>20).count();
System.out.println("count:"+count);

正常的遍历用Stream一行就可以实现了。

运行结果:

count:6

下面是一个使用了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();
System.out.println("count:" + count);

运行结果:

count:7

其实Stream.of()也是调用的Stream.of()方法来实现的。

Stream.of()

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.forEach(System.out::println);

运行结果:

3
4
8
16
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(System.out::println);

运行结果:

3
4
8
16
19
27
23

流的转换

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(String::valueOf).collect(Collectors.toList());

运行结果为:

[15, 32, 5, 232, 56]
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(Collection::stream).collect(Collectors.toList());
System.out.println(testList);

这个时候就应该使用flatMap将多个流进行合并,然后再收集到一个集合中。

List<Integer> testList = testMap.values().stream().flatMap(Collection::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();
System.out.println(first);

运行结果:

232
findAny方法

findAny方法 可以在集合中只要找到任何一个所匹配的元素,就返回,此方法在对流并行执行时十分有效(任何片段中发现第一个匹配元素都会结束计算,串行流中和findFirst返回一样)。

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 anyItem = hearList.parallelStream().filter(i->i>100).findAny().get();System.out.println(anyItem);

运行结果:

104
anyMatch方法

anyMatch方法 可以判定集合中是否还有匹配的元素。返回结果是一个boolean类型值。

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);boolean isHas = hearList.parallelStream().anyMatch(i->i>100);System.out.println(isHas);

运行结果:

true
allMatch方法和noneMatch方法

allMatch方法noneMatch方法,分别在所有元素匹配和没有元素匹配时返回true。

        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);boolean allHas = hearList.parallelStream().allMatch(i->i>100);boolean noHas = hearList.parallelStream().noneMatch(i->i>100);System.out.println(allHas);System.out.println(noHas);

运行结果:

false
false

虽然这些方法总是会检查整个流,但是仍然可以通过并行执行来提高速度。

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));
拼接

将字流中的字符串连接并收集起来。

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作为值:

@Data
@Accessors(chain = true)
class Room{private Integer high;private Integer width;private Integer length;
}
List<Room> roomList = Lists.newArrayList(new Room().setHigh(11).setWidth(23).setLength(56),new Room().setHigh(22).setWidth(46).setLength(112),new Room().setHigh(33).setWidth(92).setLength(224));
}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()));

运行结果:

{33=1, 22=3, 11=2}

summing(Int|Long|Double)方法 接受一个取值函数作为参数,来计算总和。

Map<Integer,Integer> sumMap = roomList.stream().collect(Collectors.groupingBy(Room::getHigh,Collectors.summingInt(Room::getWidth)));

运行结果:

{33=92, 22=177, 11=107}

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));
});

Java8的Stream API使用(笔记)相关推荐

  1. 【Java8新特性】关于Java8的Stream API,看这一篇就够了!!

    写在前面 Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API(java.util.stream.*)  ,那什么是Stream API呢?Java8中 ...

  2. Java8的Stream API使用

    前言 这次想介绍一下Java Stream的API使用,最近在做一个新的项目,然后终于可以从老项目的祖传代码坑里跳出来了.项目用公司自己的框架搭建完成后,我就想着把JDK版本也升级一下吧(之前的项目, ...

  3. java8之Stream API(提取子流和组合流)

    为什么80%的码农都做不了架构师?>>>    Stream.limit(n)会返回一个包含n个元素的新流(如果原始流的长度小于n,则会返回原始的流).例如: package jav ...

  4. 学习笔记之-java8的新特性-函数式接口,lambda表达式,方法引用,Stream API,Optional类

    1.Lambda表达式 用匿名内部类的方法去创建多线程1.new Thread2.参数传递new Runnable3.重写run方法4.在run方法中去设置线程任务5.调用start问题:我们最终目标 ...

  5. java8新特性-lambda表达式和stream API的简单使用

    一.为什么使用lambda Lambda 是一个 匿名函数,我们可以把 Lambda表达式理解为是 一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风 ...

  6. 【java8新特性】——Stream API详解(二)

    一.简介 java8新添加了一个特性:流Stream.Stream让开发者能够以一种声明的方式处理数据源(集合.数组等),它专注于对数据源进行各种高效的聚合操作(aggregate operation ...

  7. Java8————Stream API

    引言 Java8 加入了java.util.stream包,这个包中的相关API将极大的增强容器对象对元素的操作能力. 它专注于对集合对象进行各种便利.高效的聚合操作,或大批量数据处理. Stream ...

  8. Java8新特性总结 -5.Stream API函数式操作流元素集合

    所有示例代码打包下载 : 点击打开链接 Java8新特性 : 接口新增默认方法和静态方法 Optional类 Lambda表达式 方法引用 Stream API - 函数式操作流元素集合 Date/T ...

  9. java outputstream api,Java8 stream API以及常用方法

    Java8引入了全新的Stream API,Stream API为Java编程提供了丰富的函数式编程操作. Stream API与Java提供的其他集合类型有本质的区别,具体如下: java.io的I ...

最新文章

  1. 结构控制Switch Case
  2. 如何搭建安卓开发持续化集成环境(Ubuntu + Jenkins + SonarQube)
  3. swift语言 数组定义_Swift3中数组创建方法
  4. Linux下Openssl的安装全过程
  5. 高校教师抄袭豆瓣博主文章,学校证实:基本属实!记过并调离教学科研岗位...
  6. java+向前进一_Java 线程基础
  7. linux根目录如何改代码,linux怎样修改目录字体颜色
  8. Halcon 注册说明
  9. java的oracle考试认证(OCJP)之路
  10. 使用IDEA进行Lua代码调试、自动提示、代码跳转、智能重命名
  11. JavaSE学生教师管理系统
  12. 1043 : 最大值
  13. 苹果MacBook Air安装win7
  14. 设计 - 收藏集 - 掘金
  15. ireport怎么实现总计和小计?
  16. 苹果手表的真实触感信息(Real Touch Messaging)
  17. FileZilla ftp传输文件报错: 响应:550 Create directory operation failed.
  18. kmeans聚类目的干什么的_零基础学习Kmeans聚类算法的原理与实现过程
  19. No core dump will be written. Minidumps are not enabled by default on client versions of Windows
  20. spark decimal(38,18)超出38限制的思考

热门文章

  1. Unity 插件使用笔记
  2. 2020 HDU多校 第一场 04-Distinct Sub-palindromes(思维)
  3. 实现yolo3模型训练自己的数据集总结
  4. 物联网(IoT基本概念探讨)
  5. 安防报警系统给我们带来了什么有哪些功能
  6. 独居老人一键式报警器
  7. 如何判断一个单元格是否为合并单元格
  8. Unity SRP世界空间重建
  9. java 修改pdf图片_java代码将pdf 转换成图片加缩略图 -3
  10. C#PDF转图片,支持批量转,支持PDF文件,BASE64转换为图片文件,BASE64,支持合并PDF为一张图