Java 8 Stream distinct不起作用

Moi*_*nGK 6 java java-8 java-stream

这就是我在做的事情:

List scores = Stream.concat(oldEntries.stream(), newEntries.stream())
                    .sorted()
                    .distinct()
                    .limit(maxSize)
                    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

我期待一个没有任何重复的排序列表,但有时候列表中有重复.

我已经覆盖了hashCode和equals方法,我还观察到这些方法每次都返回正确的值.任何人都可以看到我的流有什么问题吗?

这是我的equals()和hashCode()它们由IDEA自动生成:

..
private int userId;
private int levelId;
private int score;

@Override
public boolean equals(Object o) {

    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Score score = (Score) o;

    if (userId != score.userId) return false;
    return levelId == score.levelId;

}

@Override
public int hashCode() {
    int result = userId;
    result = 31 * result + levelId;
    return result;
}

public int compareTo(Score other) {

    if (other == null) {
        return 1;
    } else {
        return Integer.compare(other.score, this.score);
    }
}

 ..
Run Code Online (Sandbox Code Playgroud)

Kay*_*man 8

您的流首先按照compareTo,即使用score.

然后使用equals(),即使用userId和"分开" levelId.根据javadoc:

对于有序流,不同元素的选择是稳定的(对于重复元素,保留在遇到顺序中首先出现的元素.)对于无序流,不进行稳定性保证.

例:

score 1, user 2, level 3
score 3, user 2, level 3
score 1, user 3, level 1
Run Code Online (Sandbox Code Playgroud)

排序后......

score 1, user 2, level 3
score 1, user 3, level 1
score 3, user 2, level 3
Run Code Online (Sandbox Code Playgroud)

区别现在什么都不做,因为元素根据用户/级别不相等.这可能会导致"重复"元素,因为您根据一件事情对流进行排序,但通过完全不同的事情确定相等性.

  • @MoienGK因为流是一个有序流,所以假设相等的元素互相跟随.在所示的示例中,情况并非如此,并且distinct无法删除得分为3的行,因为它不等于**之前的行**. (3认同)
  • @ByeBye你是什么意思?它的描述非常清楚. (2认同)
  • 优化的有效性在[此答案](/sf/answers/3066513061/)中得到了证明,但请注意,即使没有优化,也可能出现与`equals`不一致的自然顺序的问题. ,例如当使用`distinct()`而不使用`sort()`时,因为在幕后使用的`HashMap`使用自然顺序来解决哈希冲突([见这里](/sf/ask/2461525181/)/2711488))... (2认同)