Stream API可以极大提高Java程序员的生产力, 让程序员写出高效率、干净、简洁的代码.
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等.
例如, 汇总所有男性用户ID, 并根据年龄倒序排序.
采用非Stream的方式, 代码如下:
List people = new ArrayList<>();
List man = new ArrayList<>();
for (Person t : people) {
if (t.getType() == Person.SEX.MALE) {
man.add(t);
}
}
Collections.sort(man, new Comparator() {
public int compare(Person t1, Person t2)
{
return t2.getAge().compareTo(t1.getAge());
}
});
List ids = new ArrayList<>();
for (Person t : man) {
ids.add(t.getId());
}
再看下采用Stream的方式的代码:
List people = new ArrayList<>();
List ids = people.parallelStream()
.filter(t -> t.getType() == Person.SEX.MALE)
.sorted(comparing(Person::getAge).reversed())
.map(Person::getId)
.collect(toList());
可见, 采用Stream后, 代码简洁明了.
下面就一起看下Stream的常用API.
一. Stream的构建
先一起看下Stream的创建方式有哪些.
1.1 字符串Stream
Stream stream = Stream.of("a", "b", "c");
1.2 从数组创建Stream
String[] strArray = new String[]{"a", "b", "c"};
stream = Stream.of(strArray);
stream = Arrays.stream(strArray);
1.3 从集合创建Stream
List list = Arrays.asList(strArray);
stream = list.stream();
1.4 等差数列生成
Stream.iterate(0, n -> n + 1)
.limit(10)
.forEach(System.out::println);
1.5 随机数生成
Random seed = new Random();Supplierrandom = seed::nextInt;Stream.generate(random).limit(10).forEach(System.out::println);
二. Stream转换为其他对象
Stream可以很方便的进行映射转换.
2.1 转换为字符串数组
Stream stream = Stream.of("a", "b", "c");
String[] strArray1 = stream.toArray(String[]::new);
2.2 转换为集合
List list1 = stream.collect(Collectors.toList());
List list2 = stream.collect(Collectors.toCollection(ArrayList::new));
Set set1 = stream.collect(Collectors.toSet());
Stack stack1 = stream.collect(Collectors.toCollection(Stack::new));
2.3 转成字符串
String str = stream.collect(Collectors.joining());
三. Stream 遍历: forEach
3.1 数字的范围遍历
IntStream.of(new int[]{1, 2, 3}).forEach(System.out::println);IntStream.range(1, 3).forEach(System.out::println);IntStream.rangeClosed(1, 3).forEach(System.out::println);
3.2 过滤并遍历
people.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.forEach(p -> System.out.println(p.getName()));
3.3 遍历并返回新的Stream: peek
Stream.of("one", "two", "three", "four")
.filter(e -> e.length() > 3)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList());
3.4 limit和skip
Stream.of(1,2,3,4,5).limit(10).skip(3).collect(Collectors.toList()).forEach(System.out::println);
3.5 排序后遍历: sorted
Stream.of(5,4,3,2,1).sorted((p1,p2) -> p1.compareTo(p2)).limit(10).skip(3).collect(Collectors.toList()).forEach(System.out::println);
四. Stream的映射操作: map
将流中各元素进行映射操作.
4.1 将字符串映射转换为大写
List output = wordList.stream().map(String::toUpperCase).collect(Collectors.toList());
4.2 将数字转换为平方值
Listnums = Arrays.asList(1, 2, 3, 4);
ListsquareNums = nums.stream().
map(n -> n * n).
collect(Collectors.toList());
4.3 Stream扁平化: flatMap
多个Stream合并为一个
Stream> inputStream = Stream.of(
Arrays.asList(1),
Arrays.asList(2, 3),
Arrays.asList(4, 5, 6)
);
Stream outputStream = inputStream.
flatMap((childList) -> childList.stream());
五. Stream组合操作: reduce
将流中各元素进行聚合操作.
5.1 字符串连接, concat = "ABCD"
String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
5.2 求最小值, minValue = -3.0
double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);
5.3 求和, sumValue = 10, 切初始值为0
int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
5.4 求和, sumValue = 10, 无初始值
sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
5.5 过滤并连接字符串, concat = "ace"
concat = Stream.of("a", "B", "c", "D", "e", "F")
.filter(x -> x.compareTo("Z") > 0)
.reduce("", String::concat);
5.6 按年龄分组: groupingBy
Map<Integer, List> map = Stream.of(new Person()).collect(Collectors.groupingBy(Person::getAge));
六. 并行操作
parallelStream 是流并行处理程序的代替方法.
long count = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl").parallelStream().filter(string -> string.isEmpty()).count();