流
Java8 中有两大最为重要的改变。 第一个是 Lambda 表达式; 另外一个则是 Stream API(
java.util.stream.*)。
Stream 是 Java8 中处理集合的关键抽象概念, 它可以指定你希望对集合进行的操作, 可以执
行非常复杂的查找、 过滤和映射数据等操作。 使用 Stream API 对集合数据进行操作, 就类似于使
用 SQL 执行的数据库查询。
注意:Stream 不会改变源对象。
常用代码
对于java8中的stream,由于工作中不常使用,所以很容易忘记。但一旦有相应场景,使用起来很方便,在这里记录一下我使用过的常用流。
我对流操作的感受:流操作可以类比我们的sql语句,用流可以实现where、group by等。
实体类:
class Person{
private String name;
private int age;
private String province;
private String city;
public Person(String name, int age, String province, String city) {
this.name = name;
this.age = age;
this.province = province;
this.city = city;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 节约博客空间,省略getter、setter、toString
}
分组group by
private void groupBy(){
List<Person> personList = new ArrayList<>();
Person person1 = new Person("张三",13,"吉林","长春");
Person person2 = new Person("陈二",12,"吉林","四平");
Person person3 = new Person("李四",14,"辽宁","沈阳");
personList.add(person1);
personList.add(person2);
personList.add(person3);
Map collect = personList.stream().collect(Collectors.groupingBy(Person::getProvince, Collectors.groupingBy(Person::getCity)));
System.out.println(collect);
}
结果:
{吉林={四平=[Person{name='陈二', age=12, province='吉林', city='四平'}], 长春=[Person{name='张三', age=13, province='吉林', city='长春'}]}, 辽宁={沈阳=[Person{name='李四', age=14, province='辽宁', city='沈阳'}]}}
指定group by结果集,一个group by:
private void groupBy(){
List<Person> personList = new ArrayList<>();
Person person1 = new Person("张三",13,"吉林","长春");
Person person2 = new Person("张五",13,"吉林","长春");
Person person3 = new Person("陈二",12,"吉林","四平");
Person person4 = new Person("李四",14,"辽宁","沈阳");
personList.add(person1);
personList.add(person2);
personList.add(person3);
personList.add(person4);
Map<String,List<Person>> collect = personList.stream().collect(Collectors.groupingBy(Person::getProvince/*, Collectors.groupingBy(Person::getCity)*/));
System.out.println(collect);
}
指定group by结果集,两个group by:
private void groupBy(){
List<Person> personList = new ArrayList<>();
Person person1 = new Person("张三",13,"吉林","长春");
Person person2 = new Person("张五",13,"吉林","长春");
Person person3 = new Person("陈二",12,"吉林","四平");
Person person4 = new Person("李四",14,"辽宁","沈阳");
personList.add(person1);
personList.add(person2);
personList.add(person3);
personList.add(person4);
Map<String,Map<String,List<Person>>> collect = personList.stream().collect(Collectors.groupingBy(Person::getProvince, Collectors.groupingBy(Person::getCity)));
System.out.println(collect);
}
过滤filter
使用stream().filter()来过滤一个List对象,查找符合条件的对象集合。
下面示例的等效SQL:age>13 AND province=‘吉林’
private void filter(){
List<Person> personList = new ArrayList<>();
Person person1 = new Person("张三",12,"吉林","长春");
Person person2 = new Person("陈二",14,"吉林","四平");
Person person3 = new Person("陈五",15,"吉林","松原");
Person person4 = new Person("李四",16,"辽宁","沈阳");
personList.add(person1);
personList.add(person2);
personList.add(person3);
personList.add(person4);
List<Person> collect = personList.stream().filter(person -> person.getAge() > 13 && person.getProvince().equals("吉林")).collect(Collectors.toList());
System.out.println(collect);
}
结果:
[Person{name='陈二', age=14, province='吉林', city='四平'}, Person{name='陈五', age=15, province='吉林', city='松原'}]
排序sort
public void sort(){
List<Person> personList = new ArrayList<>();
Person person1 = new Person("张三",13);
Person person2 = new Person("陈二",9);
Person person3 = new Person("李四",14);
personList.add(person1);
personList.add(person2);
personList.add(person3);
// 按照年龄排序,默认升序
List<Person> collect = personList.stream().sorted(Comparator.comparing(Person::getAge)).collect(Collectors.toList());
System.out.println(collect);
}
removeIf
需求:两个集合,一个A集合,一个B集合,要求从A集合中删除(remove)AB集合相同的元素,返回新的A集合。
比如A集合有“香蕉、苹果、橘子”,B集合有“苹果、葡萄”,那么得到的就是“香蕉、橘子”
private void test(){
Test test1 = new Test("1","Bob1",121);
Test test2 = new Test("2","Bob2",122);
Test test3 = new Test("3","Bob3",123);
Test test4 = new Test("4","Bob4",124);
Test test5 = new Test("5","Bob5",125);
Test test6 = new Test("6","Bob6",126);
List<Test> all = new ArrayList<>();
all.add(test1);
all.add(test2);
all.add(test3);
all.add(test4);
all.add(test5);
List<Test> child = new ArrayList<>();
child.add(test2);
child.add(test3);
child.add(test6);
all.removeIf(item->{
return child.stream().anyMatch(childItem ->{
// 如果子集合的id和全集的id相同,就从全集内去掉该元素
return childItem.getId().equals(item.getId());
});
});
System.out.println(all);//Test(id=1, name=Bob1, age=121), Test(id=4, name=Bob4, age=124), Test(id=5, name=Bob5, age=125)
}
@Data
@AllArgsConstructor
class Test{
private String id;
private String name;
private Integer age;
// 省略了构造方法和getter setter
}
reduce
需求:合并多个相同属性的对象集合,比如下例中将所有id相同的数据age进行相加
class Test{
public static void main(String[] args) {
new Test().test();
}
void test(){
List<Student> list = new ArrayList<>();
list.add(new Student("1","Bob",12));
list.add(new Student("1","Tom",13));
list.add(new Student("2","Lily",10));
list.add(new Student("2","Ben",18));
list.add(new Student("2","Lucy",30));
list.add(new Student("3","Lily",8));
List<Student> newList = new ArrayList<>();
// parallelStream是一个并行执行的流.它通过默认的ForkJoinPool,提高你的多线程任务的速度
list.parallelStream().collect(Collectors.groupingBy(o -> o.getId(),Collectors.toList())).forEach(
// transfer 根据id分类的集合
(id, transfer)->{
System.out.println(transfer);
transfer.stream().reduce((a,b) -> new Student(a.getId(), a.getName(), a.getAge()+b.getAge()) ).ifPresent(newList::add);
}
);
System.out.println(newList);
}
@Data
@AllArgsConstructor
class Student{
private String id;
private String name;
private int age;
}
}
结果:
[SyncService.Student(id=1, name=Bob, age=12), SyncService.Student(id=1, name=Tom, age=13)]
[SyncService.Student(id=2, name=Lily, age=10), SyncService.Student(id=2, name=Ben, age=18), SyncService.Student(id=2, name=Lucy, age=30)]
[SyncService.Student(id=3, name=Lily, age=8)]
[SyncService.Student(id=1, name=Bob, age=25), SyncService.Student(id=2, name=Lily, age=58), SyncService.Student(id=3, name=Lily, age=8)]
去重
Person person1 = new Person("Bob",13);
Person person2= new Person("Bob",14);
Person person3= new Person("Tom",14);
List<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
list.add(person3);
List<Person> unique = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getName))), ArrayList::new));
System.out.println(unique);
结果:
Person(name=Bob, age=13, province=null, city=null),Person(name=Tom, age=14, province=null, city=null)
Map转换为list
// 按照打印日期分组
Map<String,List<UnitConvertRule>> result = dateList.stream().collect(Collectors.groupingBy(UnitConvertRule::getPrintDate));
// 排序
List<Map.Entry<String, List<UnitConvertRule>>> collect = result.entrySet().stream().sorted(
(time2, time1) -> Integer.valueOf(time1.getKey().replace("-", ""))
.compareTo(Integer.valueOf(time2.getKey().replace("-", ""))))
.collect(Collectors.toList());