Java 检索ArrayList中与整数最接近的多个元素

Java 检索ArrayList中与整数最接近的多个元素,java,algorithm,arraylist,Java,Algorithm,Arraylist,我有一个由对象组成的ArrayList。在这些对象中,我有一个名为level的字段 我也有一个球员的水平。我试图检索最接近玩家级别的ArrayList中的元素,但前提是玩家级别高于对象中的级别 例如: static { foodSources = new ArrayList<FoodSource>(); foodSources.add(new FoodSource("foodSource1", 10)); foodSou

我有一个由对象组成的ArrayList。在这些对象中,我有一个名为level的字段

我也有一个球员的水平。我试图检索最接近玩家级别的ArrayList中的元素,但前提是玩家级别高于对象中的级别

例如:

        static {
        foodSources = new ArrayList<FoodSource>();
        foodSources.add(new FoodSource("foodSource1", 10));
        foodSources.add(new FoodSource("foodSource2", 10));
        foodSources.add(new FoodSource("foodSource3", 10));
        foodSources.add(new FoodSource("foodSource4", 12));
        foodSources.add(new FoodSource("foodSource5", 15));
        foodSources.add(new FoodSource("foodSource6", 15));
        foodSources.add(new FoodSource("foodSource7", 15));
        foodSources.add(new FoodSource("foodSource8", 20));
        foodSources.add(new FoodSource("foodSource9", 25));
    }
如果玩家级别为10,它将检索foodSource1、foodSource2和foodSource3

如果玩家级别为11,它将检索foodSource1、foodSource2和foodSource3

但是,如果玩家级别为12,它将只检索foodSource 4

我正试图找到一种有效的方法来做这件事。我已经考虑过对ArrayList进行二进制搜索,但据我所知,您只能用它检索一个元素

大约一个半月前,我才重新开始编程,所以我不确定我可以在这里使用Java中的哪些功能


谢谢。

正确的数据结构是树形图,它是一个二叉树

提供您要查找的信息

如果你不使用树形图,你将不得不满足于搜索

int toSearch = 11;
int min = Integer.MAX_VALUE;
List<FoodSource> found = new ArrayList<>();
for (FoodSource source : foodSources) { 
    int dist = Math.abs(toSearch - source.level);
    if (dist < min) {
        min = dist;
        found.clear();
        found.add(source);
    } else if (dist == min) {
        found.add(source)
    }
}

这还将检索foodSource4,因为它是等距的,不确定您在该场景中想要什么行为

执行此操作的正确数据结构是一个树映射,它是一个二叉树

提供您要查找的信息

如果你不使用树形图,你将不得不满足于搜索

int toSearch = 11;
int min = Integer.MAX_VALUE;
List<FoodSource> found = new ArrayList<>();
for (FoodSource source : foodSources) { 
    int dist = Math.abs(toSearch - source.level);
    if (dist < min) {
        min = dist;
        found.clear();
        found.add(source);
    } else if (dist == min) {
        found.add(source)
    }
}
这还将检索食物来源4,因为它是等距的,不确定您在该场景中想要什么行为

您可以创建一个映射levelToFoodSourceMap,在其中存储该级别的级别和可用食物来源之间的关系。此外,您还可以编写一个方法,该方法在给定级别的情况下返回与玩家级别最接近的较低级别,例如

int closestLowerLevel = findClosestLevel(12);
List<FoodSource> foodSources = levelToFoodSourceMap.get(closestLowerLevel);

地图的访问权限在中,findClosestLevel可能在Ologn中实现。

您可以创建一个地图levelToFoodSourceMap,其中存储该级别的级别和可用食物源之间的关系。此外,您还可以编写一个方法,该方法在给定级别的情况下返回与玩家级别最接近的较低级别,例如

int closestLowerLevel = findClosestLevel(12);
List<FoodSource> foodSources = levelToFoodSourceMap.get(closestLowerLevel);

对地图的访问处于中,findClosestLevel可能在Ologn中实现。

removeIf 你可以使用我写的这个函数,它是基于上面提到的。 该算法首先删除级别过高的对象,然后删除级别过低的对象,最后将生成一个包含所需对象的新ArrayList

密码 请注意,我是如何创建一个新的ArrayList以不修改原始ArrayList的。

removeIf 你可以使用我写的这个函数,它是基于上面提到的。 该算法首先删除级别过高的对象,然后删除级别过低的对象,最后将生成一个包含所需对象的新ArrayList

密码
请注意我是如何创建一个新的ArrayList以不修改原始条目的。

您可以使用二进制搜索来查找第一个条目,然后遍历列表以查找其余条目。TreeMap对此有很好的支持,但它只从一个键一个级别映射到一个值,因此您必须使用一个值列表

void append(TreeMap<Integer, List<FoodSource>> map, int level, FoodSource source) {
    map.putIfAbsent(level, new ArrayList<>());
    map.get(level).add(source);
}

TreeMap<Integer, List<FoodSource>> map = new TreeMap<>();
append(map, 10, new FoodSource("foodSource1", 10));
append(map, 10, new FoodSource("foodSource1", 10));
append(map, 12, new FoodSource("foodSource1", 12));
append(map, 15, new FoodSource("foodSource1", 15));

List<FoodSource> sources = map.floorKey(12).getValue();
然而,番石榴有一个树形图可以帮你处理这些。唯一的问题是,它将值保存在一个集合而不是一个列表中,因此在给定的级别上没有项目的顺序

TreeMultimap<Integer, FoodSource> map = TreeMultimap.create();
map.put(10, new FoodSource("foodSource1", 10));
map.put(10, new FoodSource("foodSource1", 10));
map.put(12, new FoodSource("foodSource1", 12));
map.put(15, new FoodSource("foodSource1", 15));

Set<FoodSource> sources = map.get(map.keySet().floor(12));

在每种情况下,floor都意味着获取小于或等于给定级别的最大键,并可以替换为天花以获取大于或等于给定级别的最小键。

您可以使用二进制搜索来查找第一个条目,然后在列表中迭代以查找其余条目。TreeMap对此有很好的支持,但它只从一个键一个级别映射到一个值,因此您必须使用一个值列表

void append(TreeMap<Integer, List<FoodSource>> map, int level, FoodSource source) {
    map.putIfAbsent(level, new ArrayList<>());
    map.get(level).add(source);
}

TreeMap<Integer, List<FoodSource>> map = new TreeMap<>();
append(map, 10, new FoodSource("foodSource1", 10));
append(map, 10, new FoodSource("foodSource1", 10));
append(map, 12, new FoodSource("foodSource1", 12));
append(map, 15, new FoodSource("foodSource1", 15));

List<FoodSource> sources = map.floorKey(12).getValue();
TreeMultimap<Integer, FoodSource> map = TreeMultimap.create();
map.put(10, new FoodSource("foodSource1", 10));
map.put(10, new FoodSource("foodSource1", 10));
map.put(12, new FoodSource("foodSource1", 12));
map.put(15, new FoodSource("foodSource1", 15));

Set<FoodSource> sources = map.get(map.keySet().floor(12));
然而,番石榴有一个树形图可以帮你处理这些。唯一的问题是,它将值保存在一个集合而不是一个列表中,因此在给定的级别上没有项目的顺序

TreeMultimap<Integer, FoodSource> map = TreeMultimap.create();
map.put(10, new FoodSource("foodSource1", 10));
map.put(10, new FoodSource("foodSource1", 10));
map.put(12, new FoodSource("foodSource1", 12));
map.put(15, new FoodSource("foodSource1", 15));

Set<FoodSource> sources = map.get(map.keySet().floor(12));

在每种情况下,地板意味着获得小于或等于给定级别的最大关键点,可以用天花板替换,以获得大于或等于给定级别的最小关键点。

在这种情况下,关键点是级别吗?@MarcelDoe就是这样。如果您不想切换数据结构,我还为您提供了一个快速的arraylist搜索算法;然后添加到树状图:foodsources.put15,level10Sources;对的这比一个Hashmap有什么好处?在这种情况下,关键是级别吗?@MarcelDoe就是这样。如果您不想切换数据结构,我还为您提供了一个快速的arraylist搜索算法;然后添加到
TreeMultimap<Integer, FoodSource> map = TreeMultimap.create();
map.put(10, new FoodSource("foodSource1", 10));
map.put(10, new FoodSource("foodSource1", 10));
map.put(12, new FoodSource("foodSource1", 12));
map.put(15, new FoodSource("foodSource1", 15));

Set<FoodSource> sources = map.get(map.keySet().floor(12));

TreeMap:foodsources.put15,level10Sources;对的与Hashmap相比,这有什么好处?对,我将使用级别作为键来导航地图-对吗?你能解释一下恒定时间吗?我在时间复杂性方面把一篇文章和恒定时间联系了起来。右键使用最近的标高导航地图。但是你仍然需要事先找到最近的关卡。TreeMap已经能够使用floorKey或ceilingKey找到最近的关卡。不要重新发明轮子。找到准确的数字是恒定的时间,而不是找到最接近的数字。@Rubydesic你是对的,我编辑了我的答案,并对你的答案进行了升级!对,我会用关卡作为导航地图的键-对吗?你能解释一下恒定时间吗?我在时间复杂性方面把一篇文章和恒定时间联系了起来。右键使用最近的标高导航地图。但是你仍然需要事先找到最近的关卡。TreeMap已经能够使用floorKey或ceilingKey找到最近的关卡。不要重新发明轮子。找到准确的数字是恒定的时间,而不是找到最接近的数字。@Rubydesic你是对的,我编辑了我的答案,并对你的答案进行了升级!