java stream 为啥不能重用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java stream 为啥不能重用相关的知识,希望对你有一定的参考价值。

参考技术A 其实要回答“为什么”这个问题很简单,就是人家接口就是这么设计的,不能重复读。
所以今天要讨论的问题更像是:Java的InputStream为什么要设计为不能重复读?
关于InputStream为什么不能重复读取,网上也各有说法:
有的同学说:
“InputStream就类比成一个杯子,杯子里的水就像InputStream里的数据,你把杯子里的水拿出来了,杯子的水就没有了,InputStream也是同样的道理。”
比喻的非常好,让我们从直观上认识了InputStream为什么不能重复被读。
也有的同学从更深的代码角度去分析:
“在InputStream读取的时候,会有一个pos指针,他指示每次读取之后下一次要读取的起始位置,当读到最后一个字符的时候,pos指针不会重置。”
------------------------------------------------
上面是在网上摘录的,望采纳

Java编程系列Java8使用List的Stream收集转换成Set,数据却丢失了,你知道为啥吗?

热门系列:


1、前言

        前段时间,做业务时。一个列表数据,为了达到去重的效果。然后直接顺手,就用了List的stream流收集器,直接转成Set了。结果上线之后,出现了数据“莫名奇妙的”缺失情况。。。

        于是开始了日志查看情况,最终将问题定位在了类似如下这段代码处:

List<Object> list = new ArrayList<>();
Set<Object> set = list.stream().collect(Collectors.toSet());

2、正文

        因为,List集合中存储的是对象(Java中万物皆对象,所以这里可以理解成任何类型)。在做Set转换时,疏忽了Set底层的去重比较实现。。而HashSet底层正是使用了HashCode哈希算法来做比较的。所以,即使是多个内容不同的对象,都有可能会是相同的hash值,导致被认为是同一对象来处理!!(反之,2个相同内容的对象,hash值也不一定相等)

        看下面这个例子:

static class Person 
    String name;
    int age;

    public Person(String name, int age) 
        this.name = name;
        this.age = age;
    

    @Override
    public String toString()           
        return "Person" +
                "name='" + name + '\\'' +
                ", age=" + age +
                '';
    
    



public static void main(String[] args) 
    Person p1=new Person("海绵宝宝",18);
    Person p2=new Person("派大星",19);
    Person p3=new Person("蟹老板",20);
    Person p4=new Person("海绵宝宝",18);
    
    Set<Person> p=new HashSet<Person>();
    p.add(p1);
    p.add(p2);
    p.add(p3);
    p.add(p4);     
    
    //先不重写Person的equals和hashCode方法,看下HashSet存储情况
    for (Person ps:p) 
        System.out.println(ps);
    

        对于我们的业务处理来说,p1和p4这2个对象,按理应该需要做为同1个对象处理的。但是我们看下打印情况:

Personname='海绵宝宝', age=18
Personname='派大星', age=19
Personname='海绵宝宝', age=18
Personname='蟹老板', age=20

        明显,p1和p4被当做了2个不同的对象,放进了Set中。所以,此时我们如果需要做去重处理,我们应该需要重写对象的equals()hashCode()方法。

static class Person 
    String name;
    int age;

    public Person(String name, int age) 
        this.name = name;
        this.age = age;
    

    @Override
    public String toString()           //打印时输出内容,否则输出地址
        return "Person" +
                "name='" + name + '\\'' +
                ", age=" + age +
                '';
    

    @Override
    public boolean equals(Object o) 
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    

    @Override
    public int hashCode() 
        return Objects.hash(name, age);
    
    

再执行一下:

Personname='海绵宝宝', age=18
Personname='蟹老板', age=20
Personname='派大星', age=19

我们要的去重效果就达到咯!!!

        所以,回归到本文的问题点上!!!导致数据丢失的情况,则正是因为没有重写equals()hashCode()方法,导致可能有的数据有相同的Hash值,被去重处理掉了。


3、总结

        吃一堑,长一智!以此记录,共勉!!!

以上是关于java stream 为啥不能重用的主要内容,如果未能解决你的问题,请参考以下文章

java.util.Collection 为啥不实现新的 Stream 接口?

为啥具有短路操作的并行 Java Stream 会评估 Stream 的所有元素,而顺序 Stream 不会?

为啥 Java 8 Stream 上没有直接存在 toList() [重复]

Java:为啥在使用 Stream+Iterator 时不会发生 ConcurrentModificationException?

java成神之——Stream和Optional

Java8中Stream类中的forEach是抽象方法,为啥在调用的时候不用重写该方法就能实现遍历?