4

我正在阅读一本关于 Java8 的书,其中对流进行了解释。提到产生不同元素的相等性由hashCode()&equals()方法的实现决定。因此,我编写了以下代码以通过示例来理解:

static class Order{
        public Order(int id,Double value){
            this.id = id;
            this.value = value;
        }
        int id;
        Double value;
        @Override
        public int hashCode() {
            System.out.println("In Hashcode() - " + this.id +","+this.value);
            return this.id;
        }
        @Override
        public boolean equals(Object o){
            System.out.println("In Equals()");
            return this.id == ((Order)o).id;
        }
    }

    public static void main(String[] args) {
        Stream<Order> orderList = Stream.of(new Order(1,10.0),new Order(2,140.5),new Order(2,100.8));
        Stream<Order> biggerOrders = orderList.filter(o->o.value > 75.0);
        biggerOrders.distinct().forEach(o->System.out.println("OrderId:"+ o.id));
    }

它产生了以下输出:

In Hashcode() - 2,140.5
In Hashcode() - 2,140.5
OrderId:2
In Hashcode() - 2,100.8
In Equals()

我很困惑为什么在将同一个 Order 对象(2,140.5)上的 hashCode 方法与另一个 Order 对象(2,100.8)进行比较之前调用了两次。

提前致谢。

4

2 回答 2

3

正如@Adi 所回答的那样,在distinct()内部使用 HashMap 调用.hashCode()Order

这是进行两个调用的相关代码

在里面java.util.stream.DistinctOps.makeRef()

return new Sink.ChainedReference<T, T>(sink) {
    Set<T> seen;

    @Override
    public void begin(long size) {
        seen = new HashSet<>();
        downstream.begin(-1);
    }

    @Override
    public void end() {
        seen = null;
        downstream.end();
    }

    @Override
    public void accept(T t) {
        if (!seen.contains(t)) {//first call is made here
            seen.add(t);//second call is made here
            downstream.accept(t);
        }
    }
};

以下是两个调用的堆栈跟踪。

在此处输入图像描述 在此处输入图像描述

于 2016-01-02T04:21:25.687 回答
2

第一次调用 hashCode 来检查项目(订单)是否已经存在于 HashMap 中(不同的是使用内部 HashMap)。如果不存在,则第二次调用它以将项目(订单)放入哈希图中。

提示:尝试调试 hashCode 方法。

于 2016-01-02T03:58:22.957 回答