流
基本概念
流是Java8引入的全新概念,它用来处理集合中的数据,暂且可以把它理解为一种高级集合。
众所周知,集合操作非常麻烦,若要对集合进行筛选、投影,需要写大量的代码,而流是以声明的形式操作集合,它就像SQL语句,我们只需告诉流需要对集合进行什么操作,它就会自动进行操作,并将执行结果交给你,无需我们自己手写代码。
因此,流的集合操作对我们来说是透明的,我们只需向流下达命令,它就会自动把我们想要的结果给我们。由于操作过程完全由Java处理,因此它可以根据当前硬件环境选择最优的方法处理,我们也无需编写复杂又容易出错的多线程代码了。
流的操作种类
流的操作分为两种,分别为中间操作 和 终端操作。
中间操作
当数据源中的数据上了流水线后,这个过程对数据进行的所有操作都称为“中间操作”。
中间操作仍然会返回一个流对象,因此多个中间操作可以串连起来形成一个流水线。
终端操作
当所有的中间操作完成后,若要将数据从流水线上拿下来,则需要执行终端操作。
终端操作将返回一个执行结果,这就是你想要的数据。
示例
List<Person> result = list.stream()
.filter(Person::isStudent)
.collect(toList());
List<Person> result = list.stream()
.distinct()
.collect(toList());
List<Person> result = list.stream()
.limit(3)
.collect(toList());
List<Person> result = list.stream()
.skip(3)
.collect(toList());
// 映射
List<String> result = list.stream()
.map(Person::getName)
.collect(toList());
//合并多个流
List<String> list = new ArrayList<String>();
list.add("I am a boy");
list.add("I love the girl");
list.add("But the girl loves another girl");
list.stream()
.map(line->line.split(" "))
.flagmap(Arrays::stream)
.distinct()
.collect(toList());
//anyMatch
boolean result = list.stream() .anyMatch(Person::isStudent);
boolean result = list.stream() .allMatch(Person::isStudent);
boolean result = list.stream() .noneMatch(Person::isStudent);
Optional<Person> person = list.stream().findAny();
Optional介绍
Optional是Java8新加入的一个容器,这个容器只存1个或0个元素,它用于防止出现NullpointException,它提供如下方法:
isPresent()
判断容器中是否有值。
ifPresent(Consume lambda)
容器若不为空则执行括号中的Lambda表达式。
T get()
获取容器中的元素,若容器为空则抛出NoSuchElement异常。
T orElse(T other)
获取容器中的元素,若容器为空则返回括号中的默认值。
Optional<Person> person = list.stream().findFirst();
归约
归约是将集合中的所有元素经过指定运算,折叠成一个元素输出,如:求最值、平均数等,这些操作都是将一个集合的元素折叠成一个元素输出。
在流中,reduce函数能实现归约。
reduce函数接收两个参数:
初始值
进行归约操作的Lambda表达式
// 元素求和:自定义Lambda表达式实现求和 int age = list.stream().reduce(0, (person1,person2)->person1.getAge()+person2.getAge());
// 元素求和:使用Integer.sum函数求和
int age = list.stream().reduce(0, Integer::sum);
收集器
收集器用来将经过筛选、映射的流进行最后的整理,可以使得最后的结果以不同的形式展现。
collect方法即为收集器,它接收Collector接口的实现作为具体收集器的收集方法。
Collector接口提供了很多默认实现的方法,我们可以直接使用它们格式化流的结果;也可以自定义Collector接口的实现,从而定制自己的收集器。
long count = list.stream() .collect(Collectors.counting());
示例
List to Map
public class TestDuplicatedKey { public static void main(String[] args) { List<Hosting> list = new ArrayList<>(); list.add(new Hosting(1, "liquidweb.com", 80000)); list.add(new Hosting(2, "linode.com", 90000)); list.add(new Hosting(3, "digitalocean.com", 120000)); list.add(new Hosting(4, "aws.amazon.com", 200000)); list.add(new Hosting(5, "mkyong.com", 1)); list.add(new Hosting(6, "linode.com", 100000)); // new line // key = name, value - websites , but the key 'linode' is duplicated!? Map<String, Long> result1 = list.stream().collect( Collectors.toMap(Hosting::getName, Hosting::getWebsites)); System.out.println("Result 1 : " + result1); } }
public class TestSortCollect { public static void main(String[] args) { List<Hosting> list = new ArrayList<>(); list.add(new Hosting(1, "liquidweb.com", 80000)); list.add(new Hosting(2, "linode.com", 90000)); list.add(new Hosting(3, "digitalocean.com", 120000)); list.add(new Hosting(4, "aws.amazon.com", 200000)); list.add(new Hosting(5, "mkyong.com", 1)); list.add(new Hosting(6, "linode.com", 100000)); //example 1 Map result1 = list.stream() .sorted(Comparator.comparingLong(Hosting::getWebsites).reversed()) .collect( Collectors.toMap( Hosting::getName, Hosting::getWebsites, // key = name, value = websites (oldValue, newValue) -> oldValue, // if same key, take the old key LinkedHashMap::new // returns a LinkedHashMap, keep order )); System.out.println("Result 1 : " + result1); } }
List<FieldSetting> fieldSettingList = getFieldSetting(model);
// key为对象的一个属性, value为原对象
Map<String, FieldSetting> fieldSettings = fieldSettingList.stream().collect(Collectors.toMap(FieldSetting::getFieldName,f -> f));