创建实体类(后面排序会用)
import java.util.Objects;
public class Person {
int a = 1;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
a = a+100;
System.out.println("List的steam用法.Person init");
}
public void say(){
System.out.println("List的steam用法.Person num "+a);
}
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;
}
@Override
public String toString() {
return "Person{" +
"a=" + a +
", name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && name.equals(person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
测试代码,复制直接运行
import java.util.*;
import java.util.stream.Collectors;
public class List的stream用法 {
public static void main(String[] args) {
System.out.println("——————————————List中为普通类型——————————————");
List<Integer> intList = new ArrayList();
intList.add(5);
intList.add(4);
intList.add(2);
intList.add(1);
intList.add(3);
intList.add(6);
intList = intList.stream()
// 筛选小于等于5的元素
.filter(num -> num<=5)
// 排序,默认升序
.sorted()
// 保留前3条
.limit(3)
//.sorted(Comparator.comparing(Integer::byteValue,Comparator.reverseOrder()))
// 上面降序,不着急了解,可忽略
// 输出为List
.collect(Collectors.toList());
// 打印结果
intList.forEach(System.out::println);
System.out.println("——————————————List中为实体类——————————————");
List<Person> list = new ArrayList<>();
list.add(new Person("a",17));
list.add(new Person("b",17));
list.add(new Person("c4",19));
list.add(new Person("c3",19));
list.add(new Person("e",18));
list.add(new Person("f",20));
list.add(new Person("g",21));
list.add(new Person("h",21));
list = list.stream()
// 筛选年龄小于等于20岁的人
.filter(person -> person.getAge()<=20)
// 先根据年龄排序,再根据姓名排序(默认升序,降序的话追加.reversed()方法或像上面一样用Comparator.reverseOrder(),先了解,详细的比较器后面另说)
.sorted(Comparator.comparing(Person::getAge).thenComparing(Person::getName))
// 将操作后的strea转为List
.collect(Collectors.toList());
// 打印结果
list.forEach(p -> {
System.out.println(p.getName()+"——"+p.getAge());
});
System.out.println("——————————————toMap使用——————————————");
// 添加一个重复的key
list.add(new Person("a",100));
// 注意此处封装的是Map
Map<String, Integer> map = list.stream()
.collect(Collectors.toMap(
Person::getName,// 生成key
Person::getAge // 生成value
// (重点)处理key相同时的情况(oldValue和newValue名称可以随便取,前面的为key旧值,后面的为key新值,->选择保留值)
,(oldValue, newValue) -> newValue // 注释此行也可以运行,但当key重复时报异常,可以试一试
));
// 打印结果
map.forEach((key,value) ->{
System.out.println(key+"——"+value);
});
System.out.println("——————————————.map()使用——————————————");
// 加入重复数据Persn{b,17}顺带演示distinct去重
list.add(new Person("b",17));
list.add(new Person("b",17));
list.add(new Person("b",17));
List<String> collect = list.stream()
// 先去重Person
.distinct()
// 再流元素重做映射,只保留name属性,变为List<String>
.map(Person::getName)
.collect(Collectors.toList());
// 打印结果发现,只保留了name,且去重后只有一个b
collect.forEach(c -> {
System.out.println(c);
});
System.out.println("——————————————Collectors.groupingBy——————————————");
Map<Integer, List<Person>> collect1 = list.stream().collect(Collectors.groupingBy(Person::getAge));
collect1.forEach((key,value)->{
System.out.println(key);
System.out.println(value);
});
System.out.println("——————————————Collectors.joining(\"something\")——————————————");
String s = "~~~".concat(list.stream().map(Person::getName).collect(Collectors.joining(";")));
System.out.println(s);
}
}
运行结果
——————————————List中为普通类型——————————————
1
2
3
——————————————List中为实体类——————————————
a——17
b——17
e——18
c3——19
c4——19
f——20
——————————————toMap使用——————————————
c3——19
c4——19
a——100
b——17
e——18
f——20
——————————————.map()使用——————————————
a
b
e
c3
c4
f
a
——————————————Collectors.groupingBy——————————————
17
[Person{a=1, name='a', age=17}, Person{a=1, name='b', age=17}, Person{a=1, name='b', age=17}, Person{a=1, name='b', age=17}, Person{a=1, name='b', age=17}]
18
[Person{a=1, name='e', age=18}]
19
[Person{a=1, name='c3', age=19}, Person{a=1, name='c4', age=19}]
100
[Person{a=1, name='a', age=100}]
20
[Person{a=1, name='f', age=20}]
——————————————Collectors.joining("something")——————————————
~~~a;b;e;c3;c4;f;a;b;b;b
简单的使用案例,了解steam的过滤和排序以及toMap,排序部分还可以重写Comparator比较器等,需要深入了解的话可另搜文章学习,本文只展示简单使用。
案例中的API
过滤 filter(T -> boolean)
保留 boolean 为 true 的元素
排序 sorted()
排序,默认升序,也可实现 Comparable进行自定义排序
截取 limit(long n)
返回前 n 个元素,如intList.steam().limit(3)
跳过 skip(long n)
去除前 n 个元素,如intList.steam().skip(3)
去重 distinct()
去除重复元素,通过类的 equals 方法判断两个元素是否相等的
如例子中的 Person 类,要重写equals和hash方法,否则[Person{name=‘a’, age=20}, Person{name=‘a’, age=20}] 这样的情况不会处理。
映射 map(T -> R)
将流中的每一个元素 T 映射为 R(类似类型转换),注意文中map和toMap,toMap是转为key-value的Map类型,map是重做映射,还为list。
遍历 .forEach()
遍历(此方法,jdk8中List和Map都可以使用)
括号内可用函数编程,list中是x->{},区分Map的forEach中为(key,value)->{}
分组 .collect(Collectors.groupingBy(Person::getAge))
分组后的结果是Map类型,key为分组的条件,value为List<遍历的元素>
拼接 .collect(Collectors.joining(“;”))
将所有元素以指定的字符连接
其他API可自行研究
比如:
findAny() 查找元素并返回
找到其中一个元素 (使用 stream() 时找到的是第一个元素;使用 parallelStream() 并行时找到的是其中一个元素)
findFirst() 查找第一个元素并返回
找到第一个元素
anyMatch(T -> boolean) 匹配元素返回boolean
流中是否有一个元素匹配给定的 T -> boolean 条件
reduce((T, T) -> T) 和 reduce(T, (T, T) -> T) 可进行加法乘法最大值等计算
求和,求积,最大值等,可带初始值
详细案例https://blog.csdn.net/HaHa_Sir/article/details/129263866
………………