Java 查找两个数据类型的第n个最近对象

Java 查找两个数据类型的第n个最近对象,java,list,sorting,Java,List,Sorting,我试图找到离玩家最近的第n个对象,环顾四周,得出结论,2D ArrayList或List似乎是存储对象id及其到玩家的距离所需的,然后按升序排序。然而,我不知道如何通过列表来实现这一点。我目前确实有工作代码来查找最近的对象,但如果不使用大量变量,查找第n个对象似乎要困难得多 下面这个问题是我见过的最接近的答案——但是它们使用两个字符串,而不是我需要的两个不同的值,比如一个对象和一个int List nearest=new ArrayList(); add(新的ArrayList(Arrays.

我试图找到离玩家最近的第n个对象,环顾四周,得出结论,2D ArrayList或List似乎是存储对象id及其到玩家的距离所需的,然后按升序排序。然而,我不知道如何通过列表来实现这一点。我目前确实有工作代码来查找最近的对象,但如果不使用大量变量,查找第n个对象似乎要困难得多

下面这个问题是我见过的最接近的答案——但是它们使用两个字符串,而不是我需要的两个不同的值,比如一个对象和一个int

List nearest=new ArrayList();
add(新的ArrayList(Arrays.asList(instance,int))//添加一个新实例及其与玩家的距离。

目前,我遇到一个错误,数组中不允许同时使用对象和int,并且我似乎无法为这两种类型定义它。

如果我正确理解您的问题,您需要使用
游戏对象
临时存储距离,并按距离排序。 之后,您需要获得第n个
游戏对象

您可以将“游戏对象”和“距离”存储在
地图中
,并且可以使用Java 8轻松地对它们进行排序。之后,您可以从映射中获取键集作为列表,并获取第n个键集

例如,您有一张地图: (为了简单起见,我假设GameObject构造函数采用整数,举个例子)

输出:

[1, 2, 5]
因此,现在您的
sortedMap
的键集是
GameObject
s的排序列表,您可以从中轻松获得第n个:

List<GameObject> keySet = (List<GameObject>) collect.keySet();
keySet.get(n-1);
List keySet=(List)collect.keySet();
键集get(n-1);

希望有帮助

假设您有一个游戏对象的集合(集合、列表等):

Collection<GameObject> gameObjects = ...;
您需要根据这些游戏对象与玩家的距离对它们进行排序,以便获得第n个更近的对象。最简单的方法是对对象进行排序。例如:

List<GameObject> sortedGameObjects = 
    gameObjects.stream()
               .sorted(Comparator.comparingInt(gameObject -> computeDistanceToPlayer(gameObject)))
               .collect(Collectors.toList());
这就是你所需要的,但是,如果距离计算是昂贵的(需要一个长的、昂贵的计算),那么它不是真正的最优,因为它会多次计算同一个游戏对象的距离:每次排序时,它都会与另一个游戏对象进行比较。因此,如果您想避免这种情况,您可以先计算所有距离,然后将它们与游戏对象关联,然后对结果进行排序:

public class GameObjectWithDistance {
    private final GameObject gameObject;
    private final int distance;

    // constructor, getters omitted for brevity
}
现在,您只需将每个游戏对象包装在GameObjectWithDistance中,并对结果进行排序:

GameObject nthCloserGameObject = 
    gameObjects.stream()
               .map(gameObject -> new GameObjectWithDistance(gameObject, computeDistanceToPlayer(gameObject)))
               .sorted(Comparator.comparingInt(GameObjectWithDistance::getDistance))
               .skip(n - 1)
               .findFirst()
               .map(GameObjectWithDistance::getGameObject)
               .orElse(null);

现在,如果您不熟悉streams和lambda,那么可以使用循环、列表和comparator类来实现,这并不重要。重要的是逻辑,以及意识到你不需要任何类似的2D列表。

不清楚你为什么需要2D列表。你有对象。你想要第n个最近的。因此,您可以根据对象到播放器的距离对对象列表进行排序,并获取该排序列表中的第n个元素。如果GemeObject没有距离字段,并且计算距离的成本很高,那么请计算每个对象的距离,并将对象及其距离包装到另一个对象(GameObjectWithDistance)中,然后对GameObjectWithDistance列表进行排序。我的对象列表仅包含对象,我正在寻找一种方法,将距离临时存储在列表中,并在匹配其等效对象时按升序排序。正如我所说的,创建一个类来包装对象及其距离(即GameObjectWithDistance,有两个字段gameObject和distance),创建这些对象的列表,并对该列表进行排序。或者,如果计算距离很便宜,每次需要将每个游戏对象的距离与另一个游戏对象的距离进行比较时,只需计算其距离。我不太明白你的意思。抱歉,JB,如果你能发布一个带有代码示例的解决方案,那就太好了。这是我目前查找第n个对象的方法:不,这没有意义。keySet()不返回列表,而是返回一个集合。实际上,将映射的所有条目存储到一个新的HashMap中只是为了取回它的键是没有意义的。您可以将已排序的条目流映射到一个键流,并直接获取第n个键(如果您确实需要已排序的列表,也可以收集到一个列表)。在实现时遇到一些问题,但我将继续努力。你的意思是“.findFirst()”而不是“.first()”?第一个是未知的。是的,很抱歉。非常接近现在,我的代码只是没有更新每一步当我移动,有时没有选择明显的第n个最近的对象。你觉得它有什么问题吗?再次感谢您迄今为止的帮助:我很难理解为什么该方法使用x和y作为参数,但不使用它们,以及为什么将距离转换为int。如果是int,则不需要转换。如果它是类似于双精度的东西,那么使用comparingDouble()而不是comparingit()。我取出了那些x,y以使其更简单,感谢您选择了我已更改为双精度的comparingit()。此外,我还犯了很多其他的错误。我让它工作了!!非常感谢你的帮助。
Collection<GameObject> gameObjects = ...;
public int computeDistanceToPlayer(GameObject gameObject) {
    ...
}
List<GameObject> sortedGameObjects = 
    gameObjects.stream()
               .sorted(Comparator.comparingInt(gameObject -> computeDistanceToPlayer(gameObject)))
               .collect(Collectors.toList());
GameObject nthCloserGameObject = 
    gameObjects.stream()
               .sorted(Comparator.comparingInt(gameObject -> computeDistanceToPlayer(gameObject)))
               .skip(n - 1)
               .findFirst()
               .orElse(null);
public class GameObjectWithDistance {
    private final GameObject gameObject;
    private final int distance;

    // constructor, getters omitted for brevity
}
GameObject nthCloserGameObject = 
    gameObjects.stream()
               .map(gameObject -> new GameObjectWithDistance(gameObject, computeDistanceToPlayer(gameObject)))
               .sorted(Comparator.comparingInt(GameObjectWithDistance::getDistance))
               .skip(n - 1)
               .findFirst()
               .map(GameObjectWithDistance::getGameObject)
               .orElse(null);