元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。其形式好比下面的图:
+--------------------+ +------+ +------+ +---+ +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+ +------+ +------+ +---+ +-------+
以上的流程转换为 Java 代码为:
List<Integer> newList = list.stream()
.filter(b -> b.getColor() == RED)
.sorted((x,y) -> x.getWeight() - y.getWeight())
.mapToInt(Widget::getWeight)
.sum();
// 1,校验通过Collection 系列集合提供的stream()或者paralleStream()
List<String> list = new ArrayList<>();
Strean<String> stream1 = list.stream();
// 2.通过Arrays的静态方法stream()获取数组流
String[] str = new String[10];
Stream<String> stream2 = Arrays.stream(str);
// 3.通过Stream类中的静态方法of
Stream<String> stream3 = Stream.of("aa","bb","cc");
//of方法还可以装多个集合
Stream<List<Integer>> stream = Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5));
// 4.创建无限流
// 迭代
Stream<Integer> stream4 = Stream.iterate(0,(x) -> x+2);
//java 8 前
System.out.println("java 8 前");
for(User user: list){
System.out.println(user);
}
// java 8 lambda
System.out.println("java 8 lambda");
list.forEach(user -> System.out.println(user));
// java 8 stream lambda
System.out.println("java 8 stream lambda");
list.stream().forEach(user -> System.out.println(user));
2.collect(): 从流转成集合
collect方法十分强大,可以将流转成各种集合,甚至还能对进行分组等操作
List<User> list = Arrays.asList(
new User("张三", 11),
new User("王五", 20),
new User("王五", 91)
);
//将流转换为list集合
List<User> newList = list.stream().collect(Collectors.toList());
System.out.println(newList.toString());
//将流转换为map集合(以age为key,以name为value值)
Map<Integer, String> map = list.stream().collect(Collectors.toMap(User::getAge, User::getName));
//[User{age=11, name='张三'}, User{age=20, name='王五'}, User{age=91, name='王五'}]
System.out.println(map.toString());//{20=王五, 91=王五, 11=张三}
//以name相同进行分组
Map<String, List<User>> groupMap = list.stream()
.collect(Collectors.groupingBy(User::getName));
System.out.println(groupMap);
//{张三=[User{age=11, name='张三'}], 王五=[User{age=20, name='王五'}, User{age=91, name='王五'}]}
//获取stewam流
Stream<User> stream = list.stream();
//将流转换为list集合
List<User> newList = stream.collect(Collectors.toList());
//继续往下面走就会报错,因为此时stream流已经关闭了!!!
Map<Integer, String> map = stream.collect(Collectors.toMap(User::getAge, User::getName));
错误信息如下:
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:229)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.wenxue.jdk8.StreamTest.main(StreamTest.java:147)
3.filter(): 过滤,可以对原集合进行过滤,从而输出满足条件的新集合。
List<Integer> numList = Arrays.asList(1,2,3,4,5);
List<Integer> collect3 = numList.stream().filter(n -> n>3).collect(Collectors.toList());
System.out.println(collect3); //[4, 5]
如上所示,filter(n -> n>3)的第一个n是遍历的集合值,第二个表达式n>3表示要输出集合中大于3的数,于是就成功的过滤了原集合,踢掉了小于表达式的值,得到了新的集合[4,5]。
4.map(): 增强集合,可以对集合中的值进行操作,得到新的值,从而得到新的集合。
List<String> list = Arrays.asList("a", "b", "c", "d");
List<String> newList = list.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(newList); //[A, B, C, D]
如上所示,调用map方法,将原list的值都按表示式增强,进而转成大写,于是得到了增强后的集合。
map()可以对集合原始进行操作,自定义返回新的结果集;而fliter是过滤(取满足条件的值),不能修改集合元素的值
5.sorted():排序
public void testSort() {
List<Integer> nums = Arrays.asList(3, 1, 2, 5);
// java 1.8 前
System.out.println("java 8 前");
Collections.sort(list, new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getAge().compareTo(o2.getAge());
}
});
// java 1.8 stream 方法引用
nums.stream().sorted().forEach(a -> System.out.println(a));//1 2 3 5
}
从上面我们可以看出,在jdk1.8以前要实现一个排序十分的麻烦,而使用jdk1.8却可以很简单的就做到了。
如果你还想指定一个排序规则,1.8也能满足你,sorted()方法还可以提供一个参数,来用于指定比较规则:
//使用User对象的年龄排序
list.stream().sorted(Comparator.comparing(User::getAge))
.forEach(user -> System.out.println(user));
6.limit():截断,将集合截断,取截断前的值
@Test
public void testLimit(List<User> list) {
// 从第三个开始截断,只输出前三个
// java 8 前
System.out.println("java 8 前");
for (int i = 0; i < 3; i++) {
System.out.println(list.get(i));
}
// java 8 stream
System.out.println("java 8 stream");
list.stream().limit(3).forEach(user -> System.out.println(user));
}
@Test
public void testSkip() {
// 跳过前三个元素,从第四个开始输出
// java 8 前
System.out.println("java 8 前");
for (int i = 3; i < list.size(); i++) {
System.out.println(list.get(i));
}
// java 8 stream
System.out.println("java 8 stream");
list.stream().skip(3).forEach(user -> System.out.println(user));
}
/**
* 使用jdk1.8的distinct() 去重,注意:必须重写对应泛型的hashCode()和equals()方法
*/
@Test
public void testDistinct() {
// 注意使用Arrays.asList() 返回的是Arrays的内部类ArrayList,操作remove,add会报错
List<User> users = new ArrayList(list);
// 为list去除重复数据
// java 8 前
System.out.println("java 8 前");
for (int i = 0; i < users.size() - 1; i++) {
for (int j = users.size() - 1; j > i; j--) {
if (users.get(j).getAge() == users.get(i).getAge() && users.get(j).getName()
.equals(users.get(i).getName())) {
users.remove(i);
}
}
}
for (User user : users) {
System.out.println(user);
}
// java 8 stream
System.out.println("java 8 stream");
users.stream().distinct().forEach(user -> System.out.println(user));
}
list.stream().filter(user1 -> user1.getAge() > 18).distinct().sorted(
Comparator.comparing(User::getAge)).limit(2)
.forEach(user1 -> System.out.println(user));
9.mapToInt():计算,使用该方法可进行max,min,sum,avg,count等计算
/**
* 测试计算,mapToInt()方法是先返回一个可计算的对象,进而才能调用计算方法
*/
@Test
public void testNum() {
IntSummaryStatistics num = list.stream().mapToInt(u -> u.getAge())
.summaryStatistics();
System.out.println("总共人数:" + num.getCount());
System.out.println("平均年龄:" + num.getAverage());
System.out.println("最大年龄:" + num.getMax());
System.out.println("最小年龄:" + num.getMin());
System.out.println("年龄之和:" + num.getSum());
}
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
Intger num = list.stream().findFirst().get();
System.out.println(num);//1
上面我们讲到了使用of()方法可以创建集合,并且可以包裹多个集合,那么又怎样将多个再合并呢?使用flatMap()方法就能做到。
@Test
public void testFlatMap() {
//创建一个 装有两个泛型为integer的集合
Stream<List<Integer>> stream = Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5));
// 将两个合为一个
Stream<Integer> newStream = stream.flatMap(
(Function<List<Integer>, Stream<Integer>>) integers -> integers.stream());
// 转为新的集合
List<Integer> collect = newStream.collect(toList());
System.out.println("新stream大小:"+collect.size());//5
System.out.println("-----合并后-----");
collect.forEach(o -> System.out.println(o));//1,2,3,4,5
}
reduce 操作可以实现从一组元素中生成一个值
sum()
、max()
、min()
、count()
等都是reduce操作,因为常用所以设为单独函数
@Test
public void reduce() {
List<User> list = Arrays.asList(
// name,age
new User("张三", 11),
new User("王五", 20),
new User("王五", 91)
);
Optional<User> reduce = list.stream().reduce((s1, s2) -> s1.getAge() > s2.getAge() ? s1 : s2);
User user = reduce.get();
System.out.println(user); //User{age=91, name='王五'}
//当然也可以使用更简单的方法max()
Optional<User> max = list.stream().max(Comparator.comparing(User::getAge));
User user2 = max.get();
System.out.println(user2);// //User{age=91, name='王五'}
// 求年龄之和
Integer reduce3 = list.stream().reduce(0, // 该参数为初始值
(integer, user3) -> integer + user3.getAge(), // 该参数为累加器
(integer, integer2) -> integer + integer2);// 多个部分累加
System.out.println(reduce); //122
}
这里我要说明的是reduce类似于智能运算,它是一种设计思想,其中的max,count等之类的方法已经实现了这种模式。
@Test
public void reduce() {
// 使用Collectors.joining()拼接字符串
Stream<String> stream = Stream.of("张三","李四","王五","赵六");
// String s = stream.collect(Collectors.joining()); // 张三李四王五赵六
// String s = stream.collect(Collectors.joining("-")); // 张三-李四-王五-赵六
String s = stream.collect(Collectors.joining("-", "(", ")")); // (张三-李四-王五-赵六)
System.out.println(s);
}
以上就是java1.8的Stream流的所有操作方法,看以看出1.8的版本还是蛮强大的,同学们赶紧学习下吧! -- 龚文学