stream流
Stream接口
jdk1.8的新特性,核心功能:集合数据,操作集合元素
常用方法:获得stream对象的四种方法:
获得集合里面的stream(常用且推荐)
List<Integer> list=new ArrayList<>(10);
Stream<Integer> stream = list.stream();
stream里面的静态方法of
Stream<Integer> integerStream = Stream.of(1, 2, 3);
对于基本类型的stream
IntStream stream = Arrays.stream(new int[]{1, 2, 3});
Stream<Integer> boxed=stream.boxed();
random
Random random=new Random();
IntStream ints=random.ints(5,1000,10001);
filter: 过滤,筛选元素:
Stream<T> filter(Predicate<? super T> predicate
private static void demo7() {
List<User> userList=new ArrayList<>(10);
for (int i = 0; i < 50; i++) {
userList.add(new User("张三"+i,3627+i,20+i));
}
//筛选年龄大于65的对象:
//流一般都是链式的调方法,避免流中断:
List<User>list= userList.parallelStream().filter(user -> user.getAge()>65).collect(Collectors.toList());
list.forEach(System.out::println);
}
转成三部来看:
1. userList.parallelStream()创建了一个装用户的流对象
2. userList.parallelStream().filter(user -> user.getAge()>65)将年龄大于65的值给返回
3. userList.parallelStream().filter(user -> user.getAge()>65).collect(Collectors.toList());将返回的值加到集合里面
count:统计流里面的有效个数
distinct: 去除重复元素
private static void demo8() {
List<Integer> list=new ArrayList<>(10);
Collections.addAll(list,123,4,456,2,56,2,56,6,2,7,9);
//可以将list元素交给set,set集合元素值不重复,且无序
//Set<Integer> set=new HashSet<>(list);
// System.out.println(set);
list= list.parallelStream().distinct().collect(Collectors.toList());
System.out.println(list);
}
flatMap:将多个集合list合并成一个大集合
private static void demo9() {
//将数组转成集合
List<Integer> list1=Arrays.asList(12,34,54,546,2,65,78,234,675,1);
List<Integer> list2=Arrays.asList(12,3,2,34,56,3,67,2,76,2,46,7,21);
List<Integer> list3=Arrays.asList(1,23,345,1,34,2,3,5,8);
//要求三个集合合并,去重,升序,
List<Integer> lists = Stream.of(list1, list2, list3).flatMap(list->list.parallelStream()).distinct().sorted().collect(Collectors.toList());
System.out.println(lists);
}
依旧转成几部分来看:
- Stream.of(list1, list2, list3) 创建一个stream对象
- Stream.of(list1, list2, list3).flatMap(list->list.parallelStream()) 将流中所有的集合合并成一个大集合
- 然后调用stream里面的方法来去重和排序
- 最后将所有元素都收集放到一个集合里面
limit:拿到输入索引值的前几个元素
List<Integer> list1=Arrays.asList(12,34,54,546,2,65,78,234,675,1);
List<Integer> collect = list1.parallelStream().limit(3).collect(Collectors.toList());
System.out.println(collect);//12,34,54
map:一对一,对每个元素都执行处理,一直使用的是同一个stream对象
private static void demo10() {
List<User> list = new ArrayList<>(10);
Collections.addAll(list,
new User("tom", 3627, 21),
new User("jack", 3526, 20),
new User("jim", 2540, 23),
new User("jerry", 3552, 15),
new User("tom", 9884, 15)
);
//将用户的名称全部转为大写:
// list.parallelStream().map(new Function<User, Object>() {
// @Override
// public Object apply(User user) {
// return null;
// }
// });用lambda表达式来替换该内容:
List<User> collect = list.parallelStream().map(user -> {
user.setName(user.getName().toUpperCase());
return user;
}).collect(Collectors.toList());
collect.forEach(System.out::println);
}
peek:一对一,会产生新的stream对象
//将上面map方法里面的list拿过来,用peek实现,用户名称全部转为大写:
List<User> collect = list.parallelStream().peek(user -> user.setName(user.getName().toUpperCase())).collect(Collectors.toList());
collect.forEach(System.out::println);
当需要返回对象的时候可以用map,只需要得到值的时候可以peek,上面两个都是中间操作,如果不加terminal操作的话,他不会有值输出:
family.parallelStream().peek(node -> System.out.println(node)).collect(Collectors.toList());
reduce:聚合,多个元素参与运算,得到一个最终的结果
private static void demo11() {
List<User> list = new ArrayList<>(10);
Collections.addAll(list,
new User("tom", 3627, 21),
new User("jack", 3526, 34),
new User("jim", 2540, 23),
new User("jerry", 3552, 15),
new User("tom", 9884, 15)
);
//求年纪最大的:
Optional<User> optionalUser = list.parallelStream().reduce(new BinaryOperator<User>() {
@Override
public User apply(User user1, User user2) {
if (user1.getAge().compareTo(user2.getAge()) == 1) return user1;
return user2;
}
});
System.out.println(optionalUser.get());
//也可以直接在后面get用户对象
User user = list.parallelStream().reduce(new BinaryOperator<User>() {
@Override
public User apply(User user1, User user2) {
if (user1.getAge().compareTo(user2.getAge()) == 1) return user1;
return user2;
}
}).get();
System.out.println(user);
}
reduce之后得到Optional
List<Integer> list1 = Arrays.asList(12, 34, 1345, 5, 23, 53);
Integer sum = list1.parallelStream().reduce(Integer::sum).get();
System.out.println("和:"+sum);
System.out.println("平均数:"+sum/list1.size());
Integer max = list1.parallelStream().reduce(Integer::max).get();
System.out.println("最大值:"+max);
Integer min=list1.parallelStream().reduce(Integer::min).get();
System.out.println("最小值:"+min);
将stream转换成map的时候,要注意key值不可重复,否则会报异常:
Exception in thread "main" java.lang.IllegalStateException: Duplicate key 35.0
此时处理情况为:
Collections.addAll(productList,new Product(23,"薯片",35.0,4,122),
new Product(23,"薯片",356,4,122),
new Product(23,"薯片",38,4,122),
new Product(23,"薯片",39,4,122),
new Product(23,"薯片",40.0,4,122));
Map<String, Double> collect = (productList).parallelStream().limit(3).collect(Collectors.toMap(Product::getName, Product::getPrice,(product1,product2)->product2));
//后面(product1,product2)->product2)用于处理重复key值时候的情况,如果key值重复后面的数据将会覆盖前面的数据
System.out.println(collect);
Function.identity(), Product::getPrice,前一个为得到该对象,举个例子:
Map<Product, Double> collect1 = productList.parallelStream().filter(product -> product.getStore() > 50).map(product ->
{
product.setPrice(55);
return product;
}).peek(product -> product.getDiscount()).
sorted((produt1, product2) -> product2.getId().compareTo(produt1.getId())).
collect(Collectors.toMap(Function.identity(), Product::getPrice, (product1, product2) -> product2));
collect1.forEach((k,v)-> System.out.println(k+" "+v));