Stream流
用来简化集合或者数组操作,
JDK8
的新特性,需要结合Lambda
表达式一起用
Stream
流不是一个集合
Stream
流是一个集合元素的函数模型
Stream
流本身不存储任何元素或者地址值
概述、特点
- 使用
Stream流
可以将以前多步操作的代码,用一步代码就写完了(链式 流式) - 使用
Stream流
对元素进行操作编程思想: 把元素的操作比喻为流水线上加工的产品,在流水线有不同的加工环节,层层加工之后,最后出厂 - 在数据流中,是不能修改原集合数据的
Stream流
只能使用一次
步骤
- 创建一条生产线,并且把加工的产品准备好(创建
Stream流
,准备好操作的元素) - 在流水线上对产品进行层层加工(
Stream流
提供的中间操作方法) - 产品加工完下线(
Stream流
提供的终结方法)
获取Stream流
集合名.stream().forEach
,获取集合的流Stream
接口的静态方法.of
可以获取数组对应的流Map
keySet()
: 获取键集合values()
: 获取值集合
例:
HashMap<String, Integer> hm = new HashMap<>();
hm.put("Test1", 1);
hm.put("Test2", 2);
hm.put("Test3", 3);
hm.put("Test4", 4);
hm.put("Test5", 5);
Collection<Integer> values = hm.values();
values.stream().forEach(i -> {
System.out.println(i);
});
Stream中间方法
Stream
中间方法的特点: 调用完方法后,返回的还是一个Stream
流,所以可以继续调用Stream
流的方法
filter
将指定元素过滤出来
例:
List<String> list = new ArrayList<>();
list.add("Test1");
list.add("Test2");
list.add("Test3");
list.add("Test4");
list.add("Test5");
list.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return "Test2".equals(s);
}
}).forEach(s -> System.out.println(s));
list.stream().filter(s -> "Test3".equals(s))
.forEach(s -> System.out.println(s));
limit
限制遍历个数
例:
ArrayList<String> list = new ArrayList<>();
list.add("Test1");
list.add("Test2");
list.add("Test1");
list.add("Test3");
list.add("Test4");
list.add("Test5");
list.add("Test6");
list.add("Test7");
list.add("Test8");
list.add("Test6");
list.stream().limit(4).forEach(s -> System.out.println(s));
skip
跳过某些元素
例:
ArrayList<String> list = new ArrayList<>();
list.add("Test1");
list.add("Test2");
list.add("Test1");
list.add("Test3");
list.add("Test4");
list.add("Test5");
list.add("Test6");
list.add("Test7");
list.add("Test8");
list.add("Test6");
list.stream().skip(4).forEach(s -> System.out.println(s));
distinct
去除重复元素
例:
ArrayList<String> list = new ArrayList<>();
list.add("Test1");
list.add("Test2");
list.add("Test1");
list.add("Test3");
list.add("Test4");
list.add("Test5");
list.add("Test6");
list.add("Test7");
list.add("Test8");
list.add("Test6");
list.stream().distinct().forEach(s -> System.out.println(s));
concat
合并两个流
例:
ArrayList<String> list = new ArrayList<>();
ArrayList<String> list1 = new ArrayList<>();
list.add("Test1");
list.add("Test2");
list.add("Test1");
list.add("Test3");
list.add("Test4");
list.add("Test5");
list.add("Test6");
list.add("Test7");
list.add("Test8");
list.add("Test6");
list1.add("T1");
list1.add("T2");
Stream.concat(list.stream(), list1.stream()).forEach(s -> System.out.println(s));
sorted
对
Steam
流中元素进行排序
ArrayList<String> list = new ArrayList<>();
list.add("Test1");
list.add("Test2");
list.add("Test1");
list.add("Test3");
list.add("Test4");
list.add("Test5");
list.add("Test6");
list.add("Test7");
list.add("Test8");
list.add("Test6");
list.stream().sorted().forEach(s -> System.out.println(s));
Stream流的终结方法
forEach
count()
: 返回流中元素的个数
Stream流的搜集方法
返回值不是
Stream
流,所以不能进行链式编程
collect
Collectors.toList
Collectors.toSet
Collectors.toMap
例:
// 实体类
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
// 测试类
public class StreamCollectTest {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
list.add(i);
}
list.add(10);
list.add(10);
list.add(10);
list.add(10);
list.add(10);
List<Integer> collectList = list.stream().filter(i -> i % 2 == 0)
.collect(Collectors.toList());
Set<Integer> collectSet = list.stream().filter(i -> i % 2 == 0)
.collect(Collectors.toSet());
System.out.println(list);
System.out.println(collectList);
System.out.println(collectSet);
ArrayList<Student> students = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
students.add(new Student("test" + i, i));
}
Map<String, Integer> collectMap = students.stream().filter(s -> s.getAge() <= 5)
.collect(Collectors.toMap(
s -> s.getName(),
s -> s.getAge()
));
collectMap.forEach((key, value) -> {
System.out.println(key + "..." + value);
});
}
}
注
- 以上述情况搜集
Map
时会如果出现键值重复会抛出异常,推荐使用以下方式:
List<Pair<String, Double>> pairArrayList = new ArrayList<>(3);
pairArrayList.add(new Pair<>("version", 12.10));
pairArrayList.add(new Pair<>("version", 12.19));
pairArrayList.add(new Pair<>("version", 6.28));
Map<String, Double> map = pairArrayList.stream().collect(
Collectors.toMap(Pair::getKey, Pair::getValue, (v1, v2) -> v2)
);
map.entrySet().stream().forEach(
e -> System.out.println(e.getKey() + "..." + e.getValue())
);