我知道这个问题已经被问了几次,但我仍然没有找到令人满意的解决方案,而且我不确定走哪条路。问题是:
为什么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的类似问题:
答案 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()
。你从一个微不足道的小问题中创造了一个巨大的问题。无论如何,这是数据库的工作,因此您的数据集必须非常小。