java stream

stream

使用stream可以遍历一个collection(Array也可以),使用map(对每个元素执行操作)、filter(过滤)等操作产生一个新的collection。

流的操作:

  • Intermediate: map filter distinct sorted peek limit skip parallel sequential unordered
  • Terminal: forEach forEachOrdered toArray reduce collect min max count anyMatch allMatch noneMatch findFirst findAny iterator
  • Short-circuiting: anyMatch allMatch nonMatch findFirst findAny limit

*** => stream

1
2
3
4
5
6
7
8
9
// 1. Individual values
Stream stream = Stream.of("a", "b", "c");
// 2. Arrays
String [] strArray = new String[] {"a", "b", "c"};
stream = Stream.of(strArray);
stream = Arrays.stream(strArray);
// 3. Collections
List<String> list = Arrays.asList(strArray);
stream = list.stream();

stream => ***

1
2
3
4
5
6
7
8
9
// 1. Array
String[] strArray1 = stream.toArray(String[]::new);
// 2. Collection
List<String> list1 = stream.collect(Collectors.toList());
List<String> list2 = stream.collect(Collectors.toCollection(ArrayList::new));
Set set1 = stream.collect(Collectors.toSet());
Stack stack1 = stream.collect(Collectors.toCollection(Stack::new));
// 3. String
String str = stream.collect(Collectors.joining()).toString();

map

1
2
3
4
5
6
//转换大写,wordList为单词集合List<String>类型
List<String> output = wordList.stream().map(String::toUpperCase).collect(Collectors.toList());

//这段代码生成一个整数 list 的平方数 {1, 4, 9, 16}。
List<Integer> nums = Arrays.asList(1, 2, 3, 4);
List<Integer> squareNums = nums.stream().map(n -> n * n).collect(Collectors.toList());

filter

1
2
3
4
5
6
7
8
9
//留下偶数,经过条件“被 2 整除”的 filter,剩下的数字为 {2, 4, 6}。
Integer[] sixNums = {1, 2, 3, 4, 5, 6};
Integer[] evens =Stream.of(sixNums).filter(n -> n%2 == 0).toArray(Integer[]::new);

//把每行的单词用 flatMap 整理到新的 Stream,然后保留长度不为 0 的,就是整篇文章中的全部单词了。
//REGEXP为正则表达式,具体逻辑具体分析
List<String> output = reader.lines().
   flatMap(line -> Stream.of(line.split(REGEXP))).
   filter(word -> word.length() > 0).collect(Collectors.toList());

forEach

1
2
//打印所有男性姓名,roster为person集合类型为List<Pserson>
roster.stream().filter(p -> p.getGender() == Person.Sex.MALE).forEach(p -> System.out.println(p.getName()));

forEach是Terminal操作,会消费掉元素,与其功能对应的Intermediate操作为peek

reduce

reduce用于把Stream元素组合起来,它提供一个起始值,依照一个运算函数(二元),将其分别与每个元素进行运算。如果不设置起始值,返回为Optional

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 字符串连接,concat = "ABCD"
String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);

// 求最小值,minValue = -3.0
double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);

// 求和,sumValue = 10, 有起始值
int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);

// 求和,sumValue = 10, 无起始值,返回Optional,所以有get()方法
sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();

// 过滤,字符串连接,concat = "ace"
concat = Stream.of("a", "B", "c", "D", "e", "F")
  .filter(x -> x.compareTo("Z") > 0)
  .reduce("", String::concat);

sorted

1
2
3
4
5
6
7
8
9
10
List<Person> persons = new ArrayList();
for (int i = 1; i <= 5; i++) {
    Person person = new Person(i, "name" + i);
    persons.add(person);
}
List<Person> personList2 = persons.stream().limit(2).sorted((p1, p2) -> p1.getName().compareTo(p2.getName())).collect(Collectors.toList());
System.out.println(personList2);
//结果
name2
name1

Match

  • allMatch: 全部符合返回true
  • anyMatch: 有一个符合就返回true
  • noneMatch: 全部不符合返回true
1
2
3
4
5
6
7
8
9
//Match使用示例
List<Person> persons = new ArrayList();
persons.add(new Person(1, "name" + 1, 10));
persons.add(new Person(2, "name" + 2, 21));
persons.add(new Person(3, "name" + 3, 34));
persons.add(new Person(4, "name" + 4, 6));
persons.add(new Person(5, "name" + 5, 55));
boolean isAllAdult = persons.stream().allMatch(p -> p.getAge() > 18); // false
boolean isThereAnyChild = persons.stream().anyMatch(p -> p.getAge() < 12); //true

参考博客:stream介绍,以及lambda表达式的使用