检索按值排序的地图中条目周围的固定数量的条目 [英] Retrieve fixed number of entries around an entry in a map sorted by values

查看:156
本文介绍了检索按值排序的地图中条目周围的固定数量的条目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The POJO viz. Entry.java represents an entry in the leaderboard. Position is the position in the leaderboard, 1 being the user with the highest score

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中如下所示:

These entries are stored in a Map in a class as shown below :

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()应该返回

The method getLeaderBoard() is supposed to return


最多两个分数大于用户的分数(
的用户位于排行榜中用户的上方),用户的拥有
条目,并且最多两个条目紧跟在
排行榜中的用户之后

max two entries that have larger score than the user (the users that are immediately above the user in the leaderboard), the user’s own entry and max two entries that are immediately after the user in the leaderboard

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

I couldn't figure out the predicate to use to return exactly 5 entries, including the one being searched for. Another aspect is performance since the leaderBoard can have hundreds of thousands of entries.

********** Edit-1 ******* ***

**********Edit-1**********

@nullpointer提供的以下片段可以解决这个问题,但我有点想法

The following snippet provided by @nullpointer does the trick but I have some points on my mind

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可以有数百万个条目

Note : The leaderBoardUserEntryMap can have millions of entries


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

  • The indexOfnewEntry and +- 2 can cause IndexOutOfBoundsException, guarding against it seems a bit tedious, any optimal ways here?

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

Will using parallelStream() cause problems ?

列表条目= leaderBoardUserEntryMap.entrySet()。parallelStream()。sorted(Map .Entry.comparingByValue(Comparator.comparing(Entry :: getScore,Integer :: compare).reversed()))。parallel()。
map(Map.Entry :: getValue).collect(Collectors.toList());

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

推荐答案

流#limit 将帮助您限制查找顶部 N (5)用户在您创建的反转列表中,您可以使用值映射List>,并从中最终收集 List< Entry>

Stream#limit shall help you restrict finding the top N(5) users on the reversed list you've created and further you can map List> using the values and collect a List<Entry> from it finally as:

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的用例


Edit: thanks to @Yogesh for the use case


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

say there are 100 users, and the user that is being searched is at 93. List should return 91, 92, 93, 94, 95. This solution will return 1, 2, 3, 4, 5

由于用例是 subList ,可以修改为:

Since the use case is to have a subList around the current entry, this could be modified as:

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


Edit 2:


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

The indexOfnewEntry and +- 2 can cause IndexOutOfBoundsException, guarding against it seems a bit tedious, any optimal ways here?

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

Since the index of the entry might vary on the score, and the subList access further also relies on the number of output desired before/after it. Guarding shall be a better option than any other. Also what could be considered is a customSubList implementation which could internally check your collection type. How to use subList() explains this with top voted answers. I specifically liked this one though :

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




将使用 parallelStream()导致问题?

除非执行了任何 synchronized 块可能会改变并对流进行并发更新,这不会导致任何问题。

Unless there are any synchronized blocks executed that might alter and make concurrent updates to the stream it wouldn't cause any problems.

但是你应该知道何时使用并行流 - 我是否应该尽可能使用并行流?

But you should know when to use parallel stream - Should I always use a parallel stream when possible?

这篇关于检索按值排序的地图中条目周围的固定数量的条目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆