我们来了解一下 java8 的新特性,大佬写的
https://github.com/LingCoder/OnJava8
java编程思想的作者 [美] Bruce Eckel, 写的,实际上是 java编程思想的第五版;(大家都这么说)
接下来说一说 stream 怎么使用,
https://github.com/LingCoder/OnJava8/blob/master/docs/book/14-Streams.md
1.使 T 实现 java.util.function.Supplier 接口 ,然后使用 Stream.generate(T的对象实例); 来生成流;
2.通过 Stream.of(new Bubble(1), new Bubble(2), new Bubble(3)) .forEach(System.out::println);
3.如果对象本身就是实现了Collection 接口可以直接 调用 stream() 方法来获取流
最常用的当然是第三种方式,直接调用 stream() 如果是数组的话可以使用第二种方式,或者 Arrays.stream() 方法获取流;
说完流的创建,接下来说说流的生命周期;
生命周期大家肯定都不陌生,流的一般生命周期分为,创建流,操作流,收集数据,当然如果是单纯的遍历可以没有数据收集;
创建流我已经在前面交代过了,接下来说几个操作流的方法,
map();(变幻)此方法传入流中的元素,返回一个其他类型的对象,举个最简单的例子:
比如说我有个people 对象 里面 有name,age,sex,三个属性,我现在只想要name的这个属性的列表(List),那么我们就可以使用map执行如下操作
list.stream()
.map(w -> w.getName() + ",")
.forEach(System.out::print);
如此这般就可以输出 name1,name2,name3,name4,name5,
如果你会了这个,那你就可以看看mapToInt(ToIntFunction),mapToLong(ToLongFunction),mapToDouble(ToDoubleFunction)
sorted();(排序)此方法根据传入其中的比较器来排列数据,使其满足比较器的要求;
最简单的示例:
import java.util.*;
public class SortedComparator {
public static void main(String[] args) throws Exception {
//输出 10到20的
range(10, 20).forEach(t -> System.out.print(t + ","));
System.out.println();
// 以下代码 分别是 将int转换为Integer 倒序排列(Comparator默认实现了2个比较器,一个是正序,一个是倒序) 遍历输出
range(10, 20).mapToObj(Integer::new)
.sorted(Comparator.reverseOrder())
.forEach(t -> System.out.print(t + ","));
}
}
filter();(过滤/筛选)此方法根据传入其中的比较器来排列数据,使其满足比较器的要求;
过滤一般分2种情况,一种是去重,就是调用一下distinct()即可,再就是根据实际情况去判断是否保留这个元素那就要用到 filter() 了。具体咋用呢?
最简单的示例:
import java.util.*;
public class SortedComparator {
public static void main(String[] args) throws Exception {
//输出 10到20的
range(10, 20).forEach(t -> System.out.print(t + ","));
System.out.println();
// 以下代码 分别是 将int转换为Integer 倒序排列(Comparator默认实现了2个比较器,
//一个是正序,一个是倒序) 遍历输出
range(10, 20).mapToObj(Integer::new)
.sorted(Comparator.reverseOrder())
.forEach(t -> System.out.print(t + ","));
}
}
至此流的简单操作就可以说是结束了,我们下一章会继续描述哪些2个流之间不得不说的故事
最后来说一说流的收集数据,基本方法有以下几个:toArray()
:将流转换成适当类型的数组。collect(Collector)
:使用 Collector收集流元素到结果集合中。reduce(BinaryOperator)
:使用 BinaryOperator 来组合所有流中的元素。因为流可能为空,其返回值为 Optional。findFirst()
:返回第一个流元素的 Optional,如果流为空返回 Optional.empty。findAny(
:返回含有任意流元素的 Optional,如果流为空返回 Optional.empty。count()
:流中的元素个数。max(Comparator)
:根据所传入的 Comparator (比较器)所决定的“最大”元素。min(Comparator)
:根据所传入的 Comparator (比较器)所决定的“最小”元素。average()
:求取流元素平均值。sum()
:对所有流元素进行求和。
是不是一脸懵逼?????
其实很简单呐,其中最常用的有collect()
就是将流转换为List或者set ,如参分别是Collectors.toList(); Collectors.toSet(); 其次就是 toArray(),顾名思义就是将流中的元素转换为数组,这2种是属于省多少个返回多少个,剩下的这些个方法都返回一个 结果 ,就比如说 max min 就是返回最大值和最小值, 还有sum 求和 average
求平均值 count 统计个数 这些都是返回一个结果;
一般来说我们使用流都是替代for循环来做一些处理,所以后面说的其实基本上算是不常用。
其实新手最容易犯的就是分不清到底应该先调用那个方法再调用那个方法,呐~现在来看就是按照我说的顺序依次调用,再就是需要考虑好filter() 操作,因为此操作会减少元素的数量所以般是先执行这个,接下来就到了map(),最后如果需要排序的话执行sorted(),最后才是执行收集数据。
那就先啰嗦到这里 下班!!!
最后复制一些原理性的内容供大家参考:
流支持
Java 设计者面临着这样一个难题:现存的大量类库不仅为 Java 所用,同时也被应用在整个 Java 生态圈数百万行的代码中。如何将一个全新的流的概念融入到现有类库中呢?
比如在 Random 中添加更多的方法。只要不改变原有的方法,现有代码就不会受到干扰。
问题是,接口部分怎么改造呢?特别是涉及集合类接口的部分。如果你想把一个集合转换为流,直接向接口添加新方法会破坏所有老的接口实现类。
Java 8 采用的解决方案是:在接口中添加被 default
(默认
)修饰的方法。通过这种方案,设计者们可以将流式(stream)方法平滑地嵌入到现有类中。流方法预置的操作几乎已满足了我们平常所有的需求。流操作的类型有三种:创建流,修改流元素(中间操作, Intermediate Operations),消费流元素(终端操作, Terminal Operations)。最后一种类型通常意味着收集流元素(通常是到集合中)。