Java 8的Stream API
什么是Stream
Java 8引入了全新的Stream API,这里的Stream和I/O流不同,Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作,Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。
Stream 就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了。
简单应用
List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");
myList
.stream() // 创建流
.filter(s -> s.startsWith("c")) // 执行过滤,过滤出以 c 为前缀的字符串
.map(String::toUpperCase) // 转换成大写
.sorted() // 排序
.forEach(System.out::println); // for 循环打印
常用api使用
Arrays.stream()
平时处理一些数组可以使用Arrays.stream()方法来使用Stream
Integer[] array = new Integer[]{1,2,9,55,66,99,89,22,18,11,23,56};
long count = Arrays.stream(array).filter(i->i>20).count();
System.out.println(count); //7
Stream.of()
数组同时也可以将数组转成stream进行操作
Integer[] array = new Integer[]{1,2,9,55,66,99,89,22,18,11,23,56};
long count = Stream.of(array).filter(i->i>20).count();
long sum = Stream.of(12,77,59,3,654).filter(i->i>20).mapToInt(Integer::intValue).sum();
System.out.println("count:"+count+",sum:"+sum); //count:7,sum:790
filter
这是一个Stream的过滤转换,此方法会生成一个新的流,其中包含符合某个特定条件的所有元素,filter接受一个函数作为参数,该函数用Lambda表达式表示。
List<Integer> integerList = Arrays.asList(1,2,9,55,66,99,89,22,18,11,23,56);
List<Integer> after = integerList.stream()
.filter(i->i>50)
.collect(Collectors.toList());
System.out.println(after); //[55, 66, 99, 89, 56]
### 4. map
map方法指对一个流中的值进行某种形式的转换,要传递给它一个转换的函数作为参数。
List<Integer> integerList = Arrays.asList(1,2,9,55,66,99,89,22,18,11,23,56);
List<String> afterString = integerList.stream()
.map(i-> i +"个").collect(Collectors.toList());
System.out.println(afterString); //[1个, 2个, 9个, 55个, 66个, 99个, 89个, 22个, 18个, 11个, 23个, 56个]
### 5. flatMap
将多个Stream连接成一个Stream,这时候不是用新值取代Stream的值,与map有所区别,这是重新生成一个Stream对象取而代之。
List<String> words = new ArrayList<String>();
words.add("your");
words.add("name");
public static Stream<Character> characterStream(String s){
List<Character> result = new ArrayList<>();
for (char c : s.toCharArray())
result.add(c);
return result.stream();
}
Stream<Stream<Character>> result = words.stream().map(w -> characterStream(w));
//[['y', 'o', 'u', 'r'], ['n', 'a', 'm', 'e']]
Stream<Character> letters = words.stream().flatMap(w -> characterStream(w));
//['y', 'o', 'u', 'r', 'n', 'a', 'm', 'e']
limit和skip
limit(n)方法会返回一个包含n个元素的新的流(若总长小于n则返回原始流)
skip(n)方法会丢弃掉前面的n个元素 用limit和skip方法一起使用就可以实现日常的分页功能
List<Integer> pageList = myList.stream()
.skip(pageNumber*pageSize)
.limit(pageSize).collect(Collectors.toList());
distinct和sorted
distinct方法会根据原始流中的元素返回一个具有相同顺序、去除了重复元素的流。
sorted方法是需要遍历整个流的,并在产生任何元素之前对它进行排序。因为有可能排序后集合的第一个元素会在未排序集合的最后一位。
List<Integer> myTestList = Arrays.asList(10,22,10,56,10);
List<Integer> distinctList = myTestList.stream()
.distinct().collect(Collectors.toList());
System.out.println(distinctList); //[10, 22, 56]
List<Integer> myTestList = Arrays.asList(10,22,10,56,10);
List<Integer> sortList = myTestList.stream()
.sorted(Integer::compareTo).collect(Collectors.toList());
System.out.println(sortList); //[10, 10, 10, 22, 56]
Collect
//将一个流收集到一个List中。
List<Integer> thereList = hereList.stream().collect(Collectors.toList());
//收集到Set中。
Set<Integer> thereSet = hereList.stream().collect(Collectors.toSet());
//收集到Set时,控制Set的类型。
TreeSet<Integer> treeSet = hereList.stream()
.collect(Collectors.toCollection(TreeSet::new));
聚合
聚合是指将流汇聚为一个值,以便在程序中使用。聚合方法都是终止操作,聚合方法包括sum,count,max,min等。
long sum = Stream.of(12,77,59,3,654).filter(i->i>20).mapToInt(Integer::intValue).sum();
//findFirst方法返回非空集合中的第一个值,它通常与filter方法结合起来使用
Integer first = hearList.stream().filter(i->i>100).findFirst().get();
分组
对具有相同特性的值进行分组。
List<Room> roomList = Arrays.asList(
new Room(11,23,56),
new Room(11,84,48),
new Room(22,46,112),
new Room(22,75,62),
new Room(22,56,75),
new Room(33,92,224));
Map<Integer,List<Room>> groupMap = roomList.stream().collect(Collectors.groupingBy(Room::getHigh));
System.out.println("groupMap:"+groupMap);
//groupMap:{33=[Room{high=33, chang=92, kuan=224}], 22=[Room{high=22, chang=46, kuan=112}, Room{high=22, chang=75, kuan=62}, Room{high=22, chang=56, kuan=75}], 11=[Room{high=11, chang=23, kuan=56}, Room{high=11, chang=84, kuan=48}]}
more ... ...
之前工作中的使用记录
Map<Object, String> data = violations.stream().collect(Collectors.groupingBy(ConstraintViolation::getLeafBean)).values().stream().collect(Collectors.toMap(
li -> li.get(0).getLeafBean(),
li -> li.stream().map(w -> w.getMessage()).collect(Collectors.joining("/"))
));