【问题标题】:distinct() method not returning distinct elements for stream of HashSet elementsdistinct() 方法不返回 HashSet 元素流的不同元素
【发布时间】:2019-03-16 19:48:30
【问题描述】:

假设我的 Employee 类具有正确覆盖的 equals 和 hashcode 方法。

public class Employee {

private int eno;
private String firstName;
private String lastName;

@Override
public int hashCode() {
    System.out.println("hashcode called");
    final int prime = 31;
    int result = 1;
    result = prime * result + eno;
    result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
    result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    System.out.println("equals called");
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Employee other = (Employee) obj;
    if (eno != other.eno)
        return false;
    if (firstName == null) {
        if (other.firstName != null)
            return false;
    } else if (!firstName.equals(other.firstName))
        return false;
    if (lastName == null) {
        if (other.lastName != null)
            return false;
    } else if (!lastName.equals(other.lastName))
        return false;
    return true;
}
}

测试类如下

class Test {

    public static void main(String[] args) {

        Employee e1 = new Employee(1, "Karan", "Mehara");
        Employee e2 = new Employee(2, "Rajesh", "Shukla");

        Set<Employee> emps= new HashSet<>();
        emps.add(e1);
        emps.add(e2);
        System.out.println(emps);

        // No such requirement just for testing purpose modifying 
        e2.setEno(1);
        e2.setFirstName("Karan");
        e2.setLastName("Mehara");

        System.out.println(emps);

        emps.stream().distinct().forEach(System.out::println);
    }

}

上述程序的输出为:

[员工 [eno=1, firstName=Karan, lastName=Mehara], 员工 [eno=2, firstName=Rajesh, lastName=Shukla]]

[员工 [eno=1, firstName=Karan, lastName=Mehara], 员工 [eno=1, firstName=Karan, lastName=Mehara]]

员工 [eno=1, firstName=Karan, lastName=Mehara]

员工 [eno=1, firstName=Karan, lastName=Mehara]

为什么 distinct() 方法返回重复元素?

根据employee类的equals()和hashcode()方法,两个对象是一样的。

我观察到,当我调用 distinct() 方法 equals() 和 hashcode() 方法时,不会得到 Set implementation 流的调用,但它致电获取列表实施流。

按照 JavaDoc 的说法 distinct() 返回由该流的不同元素(根据 Object.equals(Object)) 组成的流。

/**
     * Returns a stream consisting of the distinct elements (according to
     * {@link Object#equals(Object)}) of this stream.
     *
     * <p>For ordered streams, the selection of distinct elements is stable
     * (for duplicated elements, the element appearing first in the encounter
     * order is preserved.)  For unordered streams, no stability guarantees
     * are made.
     *
     * <p>This is a <a href="package-summary.html#StreamOps">stateful
     * intermediate operation</a>.
     *
     * @apiNote
     * Preserving stability for {@code distinct()} in parallel pipelines is
     * relatively expensive (requires that the operation act as a full barrier,
     * with substantial buffering overhead), and stability is often not needed.
     * Using an unordered stream source (such as {@link #generate(Supplier)})
     * or removing the ordering constraint with {@link #unordered()} may result
     * in significantly more efficient execution for {@code distinct()} in parallel
     * pipelines, if the semantics of your situation permit.  If consistency
     * with encounter order is required, and you are experiencing poor performance
     * or memory utilization with {@code distinct()} in parallel pipelines,
     * switching to sequential execution with {@link #sequential()} may improve
     * performance.
     *
     * @return the new stream
     */
    Stream<T> distinct();

【问题讨论】:

  • @MirkoAlicastro 您可以比较原语(例如int,这是eno的类型),它不会通过引用而是通过值来比较它们。
  • @MirkoAlicastro 我给出的上述示例仅用于测试目的。我的问题是为什么 hashCode 和 equal 方法不会调用 If 我调用 distinct () 方法。
  • 我看错了,我以为他们都是员工对象
  • 即使是陌生人,System.out.println(e1.equals(e2));Stream 部分之前返回true
  • 答案是你做错了操作:你正在编辑一个对象,插入一个哈希图中。插入对象时,不应修改哈希码使用的字段。您应该删除它,修改它,然后重新插入它,以便在 hashmap 中给它正确的位置

标签: java java-8


【解决方案1】:

Setdefined 是“不包含重复元素的集合”。因此,Streamdistinct 方法很可能被实现为什么都不做,因为它已经保证值是唯一的。

Javadoc 中明确提到了您所做的:

注意:如果将可变对象用作集合元素,则必须非常小心。如果对象的值以影响等于比较的方式更改,而对象是集合中的一个元素,则不指定集合的​​行为。此禁令的一个特殊情况是不允许集合包含自身作为元素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-31
    • 1970-01-01
    • 2023-03-15
    • 2018-10-15
    • 2012-09-28
    • 2020-10-13
    • 1970-01-01
    相关资源
    最近更新 更多