检索按值

时间:2017-09-12 09:31:00

标签: java collections java-8 java-stream

POJO即。 Entry.java 表示排行榜中的条目。位置是排行榜中的位置,1是得分最高的用户

public class Entry {

    private String uid;
    private int score;
    private int position;

@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + score;
        result = prime * result + ((uid == null) ? 0 : uid.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;

        if (!(obj instanceof Entry))
            return false;

        Entry other = (Entry) obj;
        if (score != other.score)
            return false;
        if (uid == null) {
            if (other.uid != null)
                return false;
        } else if (!uid.equals(other.uid))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Entry [uid=" + uid + ", score=" + score + ", position=" + position + "]";
    }
}

这些条目存储在类中的Map中,如下所示:

public class GameDefault {

Map<String, Entry> leaderBoardUserEntryMap;

public void submitScore(String uid, int score) {

        Entry newEntry = new Entry(uid, score);
        leaderBoardUserEntryMap.put(uid, newEntry);
    }

public List<Entry> getLeaderBoard(String uid) {

    /* Option-3 : A Map of uid-Entry */
    leaderBoardUserEntryMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.comparing(Entry::getScore, Integer::compare).reversed()))
                .filter(/*What to put here*/);

        return null;
    }
}

方法getLeaderBoard()应该返回

  

最多两个分数大于用户的分数(用户分数)   位于排行榜中的用户之上,即用户自己的用户   条目中的条目和最多两个条目紧跟在用户之后   排行榜

我无法弄清楚用于返回5个条目的谓词,包括正在搜索的条目。另一个方面是性能,因为leaderBoard可以有数十万个条目。

**********编辑-1 **********

@nullpointer提供的以下片段可以解决这个问题,但我脑子里有一些观点

List<GameEntry> selectedEntries =  leaderBoardUserEntryMap.entrySet().stream()
            .sorted(Map.Entry.comparingByValue(Comparator.comparing(GameEntry::getScore, Integer::compare)
                    .reversed())).map(Map.Entry::getValue).collect(Collectors.toList());

int indexOfnewEntry = selectedEntries.indexOf(leaderBoardUserEntryMap.get(uid));
return  selectedEntries.subList(indexOfnewEntry-2,indexOfnewEntry+2);

注意:leaderBoardUserEntryMap可以有数百万个条目

  • indexOfnewEntry和+ - 2会导致IndexOutOfBoundsException,防止它看起来有点乏味,这里有什么最佳方式吗?

  • 使用parallelStream()会导致问题吗?

    List entries = leaderBoardUserEntryMap.entrySet()。parallelStream()。sorted(Map.Entry.comparingByValue(Comparator.comparing(Entry :: getScore,Integer :: compare).reversed()))。parallel()。                     地图(Map.Entry的::的getValue).collect(Collectors.toList());

1 个答案:

答案 0 :(得分:1)

Stream#limit将帮助您限制在您创建的反向列表中找到最高N(5)个用户,并且您还可以映射列表&gt;使用这些值并最终从中收集List<Entry>

return leaderBoardUserEntryMap.entrySet().stream()
            .sorted(Map.Entry.comparingByValue(Comparator.comparing(Entry::getScore, Integer::compare).reversed()))
            .limit(5).map(Map.Entry::getValue).collect(Collectors.toList());

编辑 :感谢@Yogesh用例

  

说有100个用户,正在搜索的用户是93。   列表应返回91,92,93,94,95。此解决方案将返回1,2,   3,4,5

由于用例是在当前条目周围有subList,因此可以修改为:

List<GameEntry> selectedEntries =  leaderBoardUserEntryMap.entrySet().stream()
            .sorted(Map.Entry.comparingByValue(Comparator.comparing(GameEntry::getScore, Integer::compare)
                    .reversed())).map(Map.Entry::getValue).collect(Collectors.toList());

int indexOfnewEntry = selectedEntries.indexOf(leaderBoardUserEntryMap.get(uid));
return  selectedEntries.subList(indexOfnewEntry-2,indexOfnewEntry+2);

编辑2

  

indexOfnewEntry和+ - 2会导致IndexOutOfBoundsException,   防范它看起来有点乏味,这里有什么最佳方式吗?

由于条目的index可能会因分数而异,subList访问权限还会依赖于之前/之后所需的输出数量。保护应该是比任何其他保护更好的选择。另外可以考虑的是customSubList实现,它可以在内部检查您的集合类型。 How to use subList()以最高投票答案解释了这一点。我特别喜欢这个:

dataList.subList(Math.max(0, first), Math.min(dataList.size(), last) );
  

使用parallelStream()会导致问题吗?

除非执行任何synchronized块可能会改变并对流进行并发更新,否则不会造成任何问题。

但您应该知道何时使用并行流 - Should I always use a parallel stream when possible?