工作中常用到的Stream流的操作

这是我工作中用的比较多的stream流操作,欢迎更多伙伴一起补充常用的操作,后续还会更新。
实体类:Device.java

package com.attack.bat.interview.java8.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.Temporal;

/**
 * @Auther: MoXi
 * @Date: 2021/05/23/11:11
 * @Description:
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Device {
    private String deviceId;
    private String parentId;
    private String deviceName;
    private String deviceAge;
    private Integer anInteger;
    private Double aDouble;
    private int anInt;
    private BigDecimal bigDecimal;
    private LocalDateTime createTime;
    private LocalDateTime receivedTime;
}

具体操作:Jdk8StreamApi.java

package com.attack.bat.interview.java8.stream;

import com.attack.bat.interview.java8.entity.Device;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * @Auther: MoXi
 * @Date: 2021/05/23/11:10
 * @Description:
 */
public class Jdk8StreamApi {
    public static void main(String[] args) {
        Device apple = new Device("1", "100", "Apple", "24", 12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
        Device apple2 = new Device("1.5", "100", "Apple2", "24", 12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
//        Device apple3 = new Device("1.5", "100", "Apple2", "24",12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
        Device huaWei = new Device("2", "200", "HuaWei", "25",12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
        Device xiaoMi = new Device("3", "300", "XiaoMi", "28",12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
        Device vivo = new Device("4", "400", "Vivo", "27",12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
        Device oppo = new Device("5", "500", "Oppo", "28",12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
        List<Device> devices = Arrays.asList(
                apple,huaWei,xiaoMi,vivo,oppo,apple2/*,apple3*/
        );
        ArrayList<Device> list = new ArrayList<>();
        list.add(apple);
        list.add(apple2);
//        list.add(apple3);
        list.add(huaWei);
        list.add(xiaoMi);
        list.add(vivo);
        list.add(oppo);
        //1、把集合的其中一个属性收集成List
        List<String> parentIds = devices.stream().map(Device::getParentId).collect(Collectors.toList());
        System.out.println("parentIds = " + parentIds);
        parentIds.forEach(System.out::println);
        System.out.println("============================================");
        //2、把集合收集成一个Map,自己指定键和值,这里指定的键不唯一会有异常 Duplicate key Apple2
        Map<String, String> idName = devices.stream().collect(Collectors.toMap(Device::getDeviceId, Device::getDeviceName));
        System.out.println("============================================");
        //3、把集合中包含某个属性的对象收集成list
        List<Device> devicesCollect = devices.stream().filter(device -> parentIds.contains(device.getParentId())).collect(Collectors.toList());
        devicesCollect.forEach(System.out::println);
        System.out.println("============================================");
        //4、将字符串分割成Integer类型的list
        String iSlitYou = "520,1314,521,1413";
        List<Integer> collect = Stream.of(iSlitYou.split(",")).map(Integer::valueOf).collect(Collectors.toList());
        System.out.println("collect = " + collect);
        System.out.println("============================================");
        //5、peek和map类似,peek的入参是consumer消费型没有返回值,map有返回值,peek适合元素的中间操作,map方法的入参为function比peek多了一个return
        Device device1 = new Device("100","100","helloworld","100",12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
        List<Device> collect1 = list.stream().filter(action -> device1.getParentId().equals(action.getParentId())).peek(action -> action.setDeviceAge(device1.getDeviceAge())).peek(System.out::println).collect(Collectors.toList());
        System.out.println("collect1 = " + collect1);
        System.out.println("list = " + list);
        System.out.println("============================================");
        //6、通过找出list中属性最大的值对象,有多个会选择比较靠前的,注意这里Device::getDeviceAge是string类型的所以28比100还大,所以改写一下
//        Device max = list.stream().max(Comparator.comparing(Device::getDeviceAge)).get();
        Device max = list.stream().max(Comparator.comparing(Device::getDeviceAge,(s1,s2) -> {
            Integer s1Int = Integer.valueOf(s1);
            Integer s2Int = Integer.valueOf(s2);
            return s1Int.compareTo(s2Int);
        })).get();
        Device min = list.stream().min(Comparator.comparing(Device::getDeviceAge,(s1,s2) -> {
            Integer s1Int = Integer.valueOf(s1);
            Integer s2Int = Integer.valueOf(s2);
            return s1Int.compareTo(s2Int);
        })).get();
        System.out.println("max = " + max);
        System.out.println("min = " + min);
        System.out.println("============================================");
        //7、通过list中的某个属性进行排序
        List<Device> collect2 = list.stream().sorted(Comparator.comparing(Device::getDeviceAge, (s1,s2) -> {
            Integer s1Int = Integer.valueOf(s1);
            Integer s2Int = Integer.valueOf(s2);
            return s1Int.compareTo(s2Int);
        })).peek(System.out::println).collect(Collectors.toList());


        System.out.println("collect2 = " + collect2);
        System.out.println("============================================");
        //8、IntStream.rangeClosed()产生指定区间的有序IntStream,与IntStream.range()不同的是,产生的元素包含最后一个,即左闭右闭。
        //IntStream是存的是int类型的stream,而Steam是一个存了Integer的stream。boxed的作用就是将int类型的stream转成了Integer类型的Stream。
        IntStream intStream = IntStream.rangeClosed(0, 5);
        System.out.println("intStream = " + intStream);
        List<Integer> integers = intStream.boxed().collect(Collectors.toList());
        System.out.println("integers = " + integers);
        //这里发现int不能放入list,Java集合不能存放基本数据类型,只能存放对象的引用。
        //每个集合元素都是一个引用变量,实际内容都存放在堆内或方法区里面
        //但是基本数据类型是在栈内存上分配空间的,栈上的数据随时会被收回。
        // ArrayList<Integer> ints = new ArrayList<int>();
        List<Device> collect3 = IntStream.rangeClosed(0,5).boxed().collect(Collectors.toList()).stream().map(number -> {
            Device device = new Device();
            device.setDeviceName(String.valueOf(number));
            System.out.println("number = " + number);
            return device;
        }).collect(Collectors.toList());
        System.out.println("collect3 = " + collect3);
        //reduce求和,这里Device::getDeviceId是字符串,所以使用Double::new转换了一下
        Double reduce = list.stream().map(Device::getDeviceId).map(Double::new).reduce(0D, Double::sum);
        System.out.println("reduce = " + reduce);
        int sum = list.stream().mapToInt(Device::getAnInt).sum();
        System.out.println("sum = " + sum);
        int sum1 = list.stream().mapToInt(Device::getAnInteger).sum();
        System.out.println("sum1 = " + sum1);
        double sum2 = list.stream().mapToDouble(Device::getADouble).sum();
        System.out.println("sum2 = " + sum2);
        BigDecimal reduce1 = list.stream().map(Device::getBigDecimal).reduce(BigDecimal.ZERO, BigDecimal::add);
        System.out.println("reduce1 = " + reduce1);
        //9、ChronoUnit.MINUTES.between(),很少用到
        Long reduce2 = list.stream().map(device -> ChronoUnit.MINUTES.between(device.getCreateTime(), device.getReceivedTime())).reduce(0L, Long::sum);
        System.out.println("reduce2 = " + reduce2);
        //10.groupingBy进行分组,以指定的属性作为key,同一组的添加到list
        Map<String, List<Device>> collect4 = list.stream().collect(Collectors.groupingBy(Device::getParentId));
        collect4.forEach((s,v) ->{
            System.out.println("s = " + s);
            System.out.println("v = " + v);
        });
        //11.自定义根据某个属性去重
        List<Device> distinctList = list.stream().filter(distinctByName(item -> item.getDeviceId())).collect(Collectors.toList());
        distinctList.forEach(System.out::println);


        //顺便复习一下map的遍历方式
        Set<String> keys = idName.keySet();
        //效率较高,较清晰
        for (String key : keys) {
            System.out.println("key = " + key);
        }
        for (String value : idName.values()) {
            System.out.println("value = " + value);
        }
        //比较方便,用的比较多
        Set<Map.Entry<String, String>> entries = idName.entrySet();
        System.out.println("entries = " + entries);
        for (Map.Entry<String, String> entry : entries) {
            System.out.println("entry.getKey() = " + entry.getKey());
            System.out.println("entry.getValue() = " + entry.getValue());
        }
        //用的也不少
        idName.forEach((s, s2) -> {
            System.out.println("s = " + s);
            System.out.println("s2 = " + s2);
        });
        //迭代器
        Iterator<Map.Entry<String, String>> iterator = idName.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<String, String> next = iterator.next();
            System.out.println("next.getKey() = " + next.getKey());
            System.out.println("next.getValue() = " + next.getValue());
        }
        //notes:在遍历过程中进行remove操作,只能用iterator遍历方式,其他的会抛出异常UnsupportedOperationException,list也是如此
        for (Device device : devices) {
            devices.remove(device);
        }
        //正确的遍历删除方式
        Iterator<Device> it = list.iterator();
        System.out.println("list = " + list);
        while (it.hasNext()){
            it.next();
            it.remove();
        }
        Collections.addAll(list,apple,huaWei,xiaoMi,vivo,oppo);
        //由于每次删除元素总会向前移动,所以从后面删除就不会出现那样的问题
        for (int i = list.size() - 1; i >= 0; i--){
            System.out.println("list.get(i) = " + list.get(i));
            list.remove(list.get(i));
        }
        //根据中间值判断再执行i++
        for (int i = 0; i < list.size(); i++) {
            System.out.println("list.get(i) = " + list.get(i));
            if (list.size() / 2 == i){
                list.remove(i);
                i--;
            }
        }

    }

    /**
     * Stream根据自定义属性去重
     * @param keyExtractor
     * @param <T>
     * @return
     */
    private static <T> Predicate<T> distinctByName(Function<? super T , Object> keyExtractor){
        Map<Object , Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迷梦星河

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值