java8之stream流
基本概念
流的含义
流:水流,IO流,数据流,指通过顺序/并行的方式将一个集合进行处理,得到新的集合。处理过程中,原来的流保持不变。
创建stream流的方式
@Test
public void testStream1(){
/**
* 创建stream
* 1、使用Collection.stream()获取串行流
*/
ArrayList<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
/**
* 2、使用Collection.parallelStream()获取并行流
*/
Stream<String> parallelStream = list.parallelStream();
/**
* 3、通过Arrays.stream()获取数组流
*/
String[] strings = new String[100];
Stream<String> stringStream = Arrays.stream(strings);
/**
* 4、通过Stream.of()创建流
*/
Stream.of("aaa","bbb","ccc");
/**
* 5、迭代创建无限流
*/
Stream<Integer> iterate = Stream.iterate(0, x -> x + 2);
iterate.limit(10)
.forEach(System.out::println);
System.out.println("generator");
/**
* 6、gengrator创建无限流
*/
Stream<Double> generate = Stream.generate(() -> Math.random());
generate.limit(100)
.forEach(System.out::println);
}
demo
List<Employee> employees = Arrays.asList(
new Employee("zhangsan",33,33.333),
new Employee("lisi",34,33333.333),
new Employee("wangwu",334,3333.333),
new Employee("songliu",3344,333.333),
new Employee("songliu",3344,333.333),
new Employee("songliu",3344,333.333),
new Employee("songliu",3344,333.333)
);
流使用-筛选与切片
filter : 接受一个lambda 进行过滤
limit : 截断流,使之不会超过指定数量
skip: 跳过流,跳过指定数量,跟limit互补
distinct: 去重,根据equals和hashcode去重
filter
@Test
public void testStream2(){
Stream<Employee> stream = employees.stream()
.filter(e -> e.getAge() > 35);
stream.forEach(System.out::println);
}
limit
@Test
public void testStream3(){
employees.stream()
.limit(2)
.forEach(System.out::println);
}
skip
@Test
public void testStream4(){
employees.stream()
.skip(3)
.forEach(System.out::println);
}
distinct
@Test
public void testStream5(){
employees.stream()
.distinct()
.forEach(System.out::println);
}
流使用-映射
映射
* map:接收lambda,将元素转化为其他形式或提取信息。接受一个函数为参数,将参数应用到每个元素上并映射成一个新的元素。
* flatmap:接受一个函数为参数,将其中每个值都转换为一个流,再将所有流合并为同一个流。
map
@Test
public void testStream3(){
List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
list.stream()
.map((x)->x.toUpperCase())
.forEach(System.out::println);
System.out.println("========================");
employees.stream()
.map(Employee::getName)
.forEach(System.out::println);
}
}
flatMap
@Test
public void testStream4(){
List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
Stream<Stream<Character>> stream = list.stream()
.map(TestStream3::getCharacterStream);
stream.forEach(t -> t.forEach(System.out::println));
System.out.println("=============================");
Stream<Character> characterStream = list.stream()
.flatMap(TestStream3::getCharacterStream);
characterStream.forEach(System.out::println);
}
public static Stream<Character> getCharacterStream(String string){
ArrayList<Character> list = new ArrayList<>();
for (char c : string.toCharArray()) {
list.add(c);
}
return list.stream();
}
a
a
a
b
b
b
c
c
c
d
d
d
e
e
e
=============================
a
a
a
b
b
b
c
c
c
d
d
d
e
e
e
流使用-排序
- sorted(): 自然排序
sorted(Comparator com): 定制排序
sorted()
@Test
public void testStream(){
List<String> list = Arrays.asList("aa", "dd", "cc", "bb");
list.stream().sorted().forEach(System.out::println);
}
sorted(Comparator com)
@Test
public void testStream2(){
employees.stream().sorted((x,y)-> Integer.compare(x.getAge(), y.getAge()))
.forEach(System.out::println);
}
流使用-查找与匹配
- 查找与匹配
* allMatch-是否匹配所有元素
* anyMatch-是否匹配至少一个元素
* noneMatch-是否无匹配元素
* findFirst-返回第一个元素
* fundAny - 返回随机一个元素
* count-返回元素和
* max-返回最大值
* min-返回最小值
allMatch
@Test
public void testStream3(){
boolean match = employees.stream()
.allMatch(x -> x.getAge() > 30);
System.out.println(match);
}
false
anyMatch
@Test
public void testStream4(){
boolean match = employees.stream()
.anyMatch(x -> x.getAge() == 180);
System.out.println(match);
}
false
noneMatch
@Test
public void test5(){
boolean b = employees.stream().noneMatch(x -> x.getAge() < 1);
System.out.println(b);
}
true
findFirst
@Test
public void test6(){
Optional<Employee> first = employees.stream().skip(2).findFirst();
System.out.println(first.get());
}
Employee(name=钱五, age=185, salary=9999.0, status=null)
findAny
@Test
public void test7(){
Optional<Employee> any = employees.stream().findAny();
System.out.println(any.get());
}
Employee(name=张三, age=18, salary=999.0, status=null)
count
@Test
public void test8(){
long count = employees.stream().count();
System.out.println(count);
}
6
max
@Test
public void test9(){
Optional<Employee> max = employees.stream()
.max((x,y) -> Integer.compare(x.getAge(),y.getAge()));
System.out.println(max);
}
Optional[Employee(name=钱五, age=185, salary=9999.0, status=null)]
min
@Test
public void test10(){
Optional<Employee> min = employees.stream()
.min((x, y) -> Integer.compare(x.getAge(), y.getAge()));
System.out.println(min);
}
Optional[Employee(name=张三, age=18, salary=999.0, status=null)]
流使用-规约
reduce
reduce(T identity,BinaryOperator) 将元素反复结合为一个值
@Test
public void testStream(){
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
Integer reduce = list.stream().reduce(1, (x, y) -> x + y);
System.out.println(reduce);
System.out.println("=========计算工资和=========");
Optional<Double> optional = employees.stream().map(Employee::getSalary)
.reduce(Double::sum);
System.out.println(optional.get());
}
46
========= 计算工资和 =========
41994.0
流使用-收集
collect-将流转换为其他形式,接受一个Collector接口实现,用于给Stream元素做汇总
@Test
public void testStream2(){
// 将员工名字收集到一个集合中
List<String> list = employees.stream()
.map(Employee::getName)
.collect(Collectors.toList());
list.forEach(System.out::println);
System.out.println("-分割线-");
Set<String> set = employees.stream()
.map(Employee::getName)
.collect(Collectors.toSet());
set.forEach(System.out::println);
System.out.println("-分割线:使用特殊集合存储-");
LinkedList<String> collect = employees.stream()
.map(Employee::getName)
.collect(Collectors.toCollection(LinkedList::new));
collect.forEach(System.out::println);
}
张三
李四
钱五
宋六
孙七
孙七
王八
-分割线-
李四
钱五
孙七
张三
宋六
王八
-分割线:使用特殊集合存储-
张三
李四
钱五
宋六
孙七
孙七
王八
collect提供的Collectors使用
@Test
public void test2(){
System.out.println("总数");
Long aLong = employees.stream()
.collect(Collectors.counting());
System.out.println(aLong);
System.out.println("平均值");
Double collect = employees.stream()
.collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println(collect);
System.out.println("总和");
Double aDouble = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));
System.out.println(aDouble);
System.out.println("最大值");
Optional<Employee> optional = employees.stream().collect(Collectors.maxBy((e, f) -> Double.compare(e.getSalary(), f.getSalary())));
System.out.println(optional.get().getSalary());
System.out.println("最小值");
Optional<Double> collect1 = employees.stream().map(Employee::getSalary).collect(Collectors.minBy(Double::compare));
System.out.println(collect1.get());
}
总数
7
平均值
7427.571428571428
总和
51993.0
最大值
9999.0
最小值
999.0
分组
@Test
public void test3(){
Map<Employee.Status, List<Employee>> map = employees.stream().collect(Collectors.groupingBy(Employee::getStatus));
System.out.println(map);
}
{FREE=[Employee{name=‘张三’, age=18, salary=999.0, status=FREE}, Employee{name=‘李四’, age=183, salary=9999.0, status=FREE}], BUSY=[Employee{name=‘钱五’, age=185, salary=9999.0, status=BUSY}, Employee{name=‘宋六’, age=184, salary=9999.0, status=BUSY}], VACATION=[Employee{name=‘孙七’, age=183, salary=9999.0, status=VACATION}, Employee{name=‘孙七’, age=183, salary=9999.0, status=VACATION}, Employee{name=‘王八’, age=128, salary=999.0, status=VACATION}]}
多级分组
@Test
public void test4(){
Map<Employee.Status, Map<String, List<Employee>>> map = employees.stream()
.collect(Collectors.groupingBy(Employee::getStatus
, Collectors.groupingBy((e) ->
{
if (e.getAge() < 20) {
return "青年";
} else {
return "老年";
}
}
)));
System.out.println(map);
}
{VACATION={老年=[Employee{name=‘孙七’, age=183, salary=9999.0, status=VACATION}, Employee{name=‘孙七’, age=183, salary=9999.0, status=VACATION}, Employee{name=‘王八’, age=128, salary=999.0, status=VACATION}]}, FREE={青年=[Employee{name=‘张三’, age=18, salary=999.0, status=FREE}], 老年=[Employee{name=‘李四’, age=183, salary=9999.0, status=FREE}]}, BUSY={老年=[Employee{name=‘钱五’, age=185, salary=9999.0, status=BUSY}, Employee{name=‘宋六’, age=184, salary=9999.0, status=BUSY}]}}
分区
@Test
public void test5(){
Map<Boolean, List<Employee>> collect = employees.stream()
.collect(Collectors.partitioningBy((e) -> e.getAge()>20));
System.out.println(collect);
}
{false=[Employee{name=‘张三’, age=18, salary=999.0, status=FREE}], true=[Employee{name=‘李四’, age=183, salary=9999.0, status=FREE}, Employee{name=‘钱五’, age=185, salary=9999.0, status=BUSY}, Employee{name=‘宋六’, age=184, salary=9999.0, status=BUSY}, Employee{name=‘孙七’, age=183, salary=9999.0, status=VACATION}, Employee{name=‘孙七’, age=183, salary=9999.0, status=VACATION}, Employee{name=‘王八’, age=128, salary=999.0, status=VACATION}]}
数据处理
@Test
public void test6(){
DoubleSummaryStatistics collect = employees.stream()
.collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println(collect.getAverage());
System.out.println(collect.getMax());
System.out.println(collect.getSum());
System.out.println(collect.getCount());
}
7427.571428571428
9999.0
51993.0
7
连接字符串
@Test
public void test07(){
String collect = employees.stream().map(Employee::getName).collect(Collectors.joining(",","111","000"));
System.out.println(collect);
}
111张三,李四,钱五,宋六,孙七,孙七,王八000八
Map遍历
map.forEach((k,v)->{
v.forEach(System.out::println);
});