Streams遵循"what,no how"原则。
学习Stream的前提是掌握Lambda表达式!
int sum = widgets.stream()
.filter(w -> w.getColor() == RED)
.mapToInt(w -> w.getWeight())
.sum();
stream()创建流;filter,mapToInt()转换;sum()终止。
流的创建主要有以下几种:
Stream<String> colle = new ArrayList<String>().stream();
int[] ints = {1, 2, 3};
Arrays.stream(ints);
Arrays.stream(ints, 1, 2);//可以指定生成的起始和终点
Stream.of(1, 2, 3);
Stream<String> silence = Stream.empty();
Path path = Paths.get("D:\\hhh\\test.xml");
Files.lines(path).forEach(System.out::println);
//常量Stream
Stream<String> echos = Stream.generate(() -> "Echo");
//随机数Stream
Stream<Double> randoms = Stream.generate(Math::random);
Stream.iterate(new Integer(1), (x)-> x+1).forEach(System.out::println);
filter(),map(),flatMap()
例如筛选字符串长度,通常流中的元素个数会减少。
List<String> list = Arrays.asList("a", "ab", "ba", "c");
list.stream()
.filter((x)-> x.length() > 1)
.forEach(System.out::println);
输出:
ab
ba
例如大小写转换。流中元素个数不变。
List<String> list = Arrays.asList("a", "ab", "ba", "c");
list.stream()
.map(w -> w.toUpperCase())
.forEach(System.out::println);
输出:
A
AB
BA
C
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "ab", "ba", "c");
list.stream()
.flatMap(w -> letters(w))
.forEach(System.out::println);
}
/**
* 将字符串s分割成由单个字符组成的List,再通过stream方法转成流。
* @param s
* @return
*/
public static Stream<String> letters(String s) {
List<String> result = new ArrayList<>();
for (int i = 0; i < s.length(); i++) {
result.add(s.substring(i, i + 1));
}
return result.stream();
}
输出:
a
a
b
b
a
c
List<String> list = Arrays.asList("a", "ab", "ba", "c");
list.stream()
.limit(2L)
.forEach(System.out::println);
输出:
a
ab
List<String> list = Arrays.asList("a", "ab", "ba", "c");
list.stream()
.skip(2L)
.forEach(System.out::println);
输出:
ba
c
List<String> list = Arrays.asList("a", "ab", "ba", "c");
List<String> list1 = Arrays.asList("1", "2", "3", "4");
Stream.concat(list.stream(), list1.stream()).forEach(System.out::println);
输出:
a
ab
ba
c
1
2
3
4
List<String> list = Arrays.asList("a", "a", "ab", "ba", "c");
list.stream()
.distinct()
.forEach(System.out::println);
输出
a
ab
ba
c
sorted有两个实现方法,一个是无参的 一个是有参的。
Stream sorted()。
Stream sorted(Comparator comparator)。
List<String> list = Arrays.asList("a", "a", "ab", "ba", "c");
list.stream()
.forEach(w -> System.out.print(w + " "));
System.out.println();
list.stream()
.sorted(Comparator.comparing(w -> w.length()))
.forEach(w -> System.out.print(w + " "));
输出
a a ab ba c
a a c ab ba
通常收集结果会消费掉流,但是使用peek不会消费掉流,而被视为一个中间操作。
List<String> list = Arrays.asList("a", "a", "ab", "ba", "c");
list.stream()
.peek(x -> System.out.println("peek:" + x))
.filter(x -> x.length() > 1)
.forEach(System.out::println);
输出:
peek:a
peek:a
peek:ab
ab
peek:ba
ba
peek:c
无参的toArray方法直接返回Object[]对象。
而 A[] toArray(IntFunction generator),返回对应的类型。例如toArray(String[]::new)返回String[].
List<String> list = Arrays.asList("a", "a", "ab", "ba", "c");
String[] strings = list.stream()
.filter(x -> x.length() > 1)
.toArray(String[]::new);
System.out.println(Arrays.toString(strings));//[ab, ba]
,
为分隔符拼接 List<String> list = Arrays.asList("a", "a", "ab", "ba", "c");
List<String> strings = list.stream()
.filter(x -> x.length() > 1)
.collect(Collectors.toList());
System.out.println(strings); //[ab, ba]
Set<String> set = list.stream()
.filter(x -> x.length() > 0)
.collect(Collectors.toSet());
System.out.println(set);//[a, ab, c, ba]
List<String> list = Arrays.asList("a", "a", "ab", "ba", "c");
String s = list.stream()
.filter(x -> x.length() > 0)
.collect(Collectors.joining("+"));
System.out.println(s);//a+a+ab+ba+c
IntSummaryStatistics collect(Collectors.summarizingInt(String::length))
:将stream转为可计算的数字类型
List<String> list = Arrays.asList("a", "a", "ab", "ba", "c");
IntSummaryStatistics collect = list.stream()
.filter(x -> x.length() > 0)
.collect(Collectors.summarizingInt(String::length));
System.out.println(collect.getMax()); // 2
Stream 有三个 match 方法,从语义上说:
List<String> list = Arrays.asList("a", "a", "ab", "ba", "c");
boolean noneMatch = list.stream().noneMatch("c"::equals);
boolean allMatch = list.stream().allMatch("c"::equals);
boolean anyMatch = list.stream().anyMatch("c"::equals);
System.out.println("noneMatch(没有任何一个匹配):" + noneMatch + "\nallMatch(所有都匹配):"+allMatch +"\nanyMatch(有一个匹配):"+anyMatch);
输出:
noneMatch(没有任何一个匹配):false
allMatch(所有都匹配):false
anyMatch(有一个匹配):true
修改输入为:
List<String> list = Arrays.asList("a", "a");
boolean noneMatch = list.stream().noneMatch("c"::equals);
boolean allMatch = list.stream().allMatch("a"::equals);
boolean anyMatch = list.stream().anyMatch("a"::equals);
System.out.println("noneMatch(没有任何一个匹配):" + noneMatch + "\nallMatch(所有都匹配):"+allMatch +"\nanyMatch(有一个匹配):"+anyMatch);
输出:
noneMatch(没有任何一个匹配):true
allMatch(所有都匹配):true
anyMatch(有一个匹配):true
这个讲解的话引入一个People类比较好讲,详见文章:
https://blog.csdn.net/sayWhat_sayHello/article/details/90199440
reduce方法需要先了解java8中新增的Optional类型和lambda中的函数式接口BinaryOperator,理解了这两个之后才能比较好的去使用。
BinaryOperator代表接受两个T类型的参数,然后返回一个T类型的值:
List<String> list = Arrays.asList("a", "a", "ab", "ba", "c");
System.out.println(list.stream().reduce((x, y) -> x + y).orElse("hhh"));
reduce操作后返回Optional,由于结果不为空所以不会返回"hhh",而是输出:
aaabbac
相当于一直迭代: “a”+“a” = “aa”, “aa”+“ab” =“aaab” ……
IntStream,LongStream,DoubleStream和对象stream的差异: