为什么Java库没有提供`HashSet.get(Object o)`和`HashMap.getKey(Object o)`

时间:2014-08-04 11:33:35

标签: java collections

我知道这个问题已经被问了几次,但我仍然没有找到令人满意的解决方案,而且我不确定走哪条路。问题是:

为什么Java库没有提供HashSet.get(Object o)HashMap.getKey(Object o)方法来返回地图中提供相同实例的实际实例?例如:

// Retrieve a house with ID=10 that contains additional information like size,
// location and price.
houses.get(new House(10));

我认为可以找到最佳答案here。所以这里是我所知道的答案的混合物:

  • 为什么你已经拥有该实例?尝试获取已有的相同对象是没有意义的。对象有一个标识符(控制它与其他Foo类型的相等)加上任何其他字段没有贡献它的身份。我希望能够通过构建一个“等于”的对象来获取Set中的对象(包括额外的字段)。 Foo对象(文本取自其中一条评论)。 - >没有答案

  • 迭代Collection并使用equals()搜索实例。这使用线性搜索,在大型集合中速度极慢。 - >错误答案

  • 使用HashMap而不是HashSet 我不需要地图,我认为用{{1}这样的方法返回地图是不够的}}。 getter应该返回getHouses()而不是Set

  • 使用Map - 不知道

  • 下面这个hacky代码(仅限Java 8 TreeSet.ceiling)使用反射并提供缺少的功能。我没有在其他答案中找到这样的东西(毫不奇怪)。如果定义了目标Java版本并且未来的Java版本最终会提供这样的方法,那么这可能是一个可接受的解决方案,现在我们有了HashSet个接口方法。人们可以想到default


default E get(E o){stream().filter(e->e.equals(o)).findAny().orElse(null);}

以下是问题:

  • 使用// Alternative: Subclass HashSet/HashMap and provide a get()/getKey() methods public static <T> T getFromSet(HashSet<T> set, T key) throws Exception { Field mapField = set.getClass().getDeclaredField("map"); mapField.setAccessible(true); HashMap<T, Object> map = (HashMap) mapField.get(set); Method getNodeMethod = map.getClass().getDeclaredMethod("getNode", int.class, Object.class); getNodeMethod.setAccessible(true); return (T) ((Map.Entry) getNodeMethod.invoke(map, key.hashCode(), key)).getKey(); } 代替HashMap<House, House>
  • 是最佳解决方案
  • 那里有另一个提供此功能并支持并发访问的库吗?
  • 您是否知道解决此功能的错误?

关于SO的类似问题:

2 个答案:

答案 0 :(得分:2)

这种行为未被照顾的原因是,创建一个包含无效数据的House实例只是为了获得一个有效数据的实例,这种设计真的很糟糕。

组合是正确的解决方案:

/** immutable class containing all the fields defining identity */
public final class HouseIdentifier {
    private final String id;
}

public class House {
    private final HouseIdentifier id;
    /** all the mutable, ephemeral properties of the house should go here */
    private int size;
    private Person owner;
}

如果您像这样设计类层次结构,那么查找所需的只是一个简单明了的Map<HouseIdentifier, House>

答案 1 :(得分:0)

Map没有getKey(Object o),因为它不是双向地图。它只将键映射到值,而不是相反。

Set没有get(Object o),因为这是Map的工作。

House对象映射到另一个House对象只是你的糟糕设计。您希望通过地址或数字或类似物获得House,因此您有一个或多个地图可以为您提供这些映射(或者更有可能是数据库)。你的问题只对你有意义,因为你在想“以错误的方式”。

您的“错误的思维方式”可以通过您的陈述来证明

  

我不需要地图,我认为在地图中返回地图是不够的   像getHouses()这样的方法。 getter应返回Set而不是Map。

我从未听说过吸气剂无法返回地图。虽然我可能会将其命名为getHouseMap()。你从一个微不足道的小问题中创造了一个巨大的问题。无论如何,这是数据库的工作,因此您的数据集必须非常小。