Пытаюсь разобраться в define () для потоков в Java8
Я просматривал книгу по 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()
Меня смущает, почему метод hashCode для одного и того же объекта Order (2140,5) вызывается дважды, прежде чем сравнивать его с другим объектом Order (2100,8).
Заранее спасибо.
2 ответа
Первый раз вызывается hashCode, чтобы проверить, присутствует ли элемент (заказ) в HashMap (в отличие от внутреннего HashMap). Во второй раз вызывается поместить элемент (заказ) в хэш-карту, если он отсутствует.
Совет: Попробуйте отладить метод hashCode.
Как ответил @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);
}
}
};
Ниже приведена трассировка стека для обоих вызовов.