假设我有一个简单的Java对象,我们称之为DefinedData。它将包含许多不同类型的最终字段,例如字符串,整数,枚举,甚至可能是一组或两个字符串。总而言之,它只是一个相对简单的数据容器。这些中可能存在1k到2k,所有静态最终对象。大多数这些字段都是唯一的,因为没有其他DefinedData对象具有该字段的相同值。
这些将放入(DefinedData,Object)的Map中。现在,如果你有DefinedData对象,你可以轻松地从地图中获取该对象,但是如果你只有一个唯一的字段值呢?你不能把它传递给地图。您必须迭代键并检查,这将意味着使用查找方法为DefinedData中的每个字段包装地图。可行,但不是最漂亮的东西,特别是如果地图中有很多值和很多查找,这是可能的。无论是那个还是需要查找DefinedData对象,这将再次成为一堆地图......
这几乎听起来像是数据库的工作(基于任何列查找),但这不是解决这个特定问题的好方法。我还宁愿避免使用十几个不同的地图,每个地图都将一个字段从DefinedData映射到Object。我见过的多键映射不适用,因为它们需要所有键值,而不仅仅是一个。是否有可以处理此特定问题的Map,Collections或其他实现?
答案 0 :(得分:0)
避免使用多个映射的唯一方法是以某种方式迭代所有DefinedData对象。原因是,你无法知道如何将它们分开或排序,直到提出请求为止。
如果你有一桶苹果,可以举一个例子。在任何时候,有人可能会出现并要求某种颜色,某种颜色或某种尺寸。您必须选择按其中一个类别进行排序,并且必须通过所有苹果搜索其他类别。 如果只有你可以有三套相同的苹果;每个类别一个。
拥有多个地图将是一个更快的解决方案,虽然占用更多的内存,而迭代将更容易实现,更慢,并使用更少的内存。
答案 1 :(得分:0)
我毫不犹豫地建议这一点,但您可以将查找封装在某种Indexer
类后面,该类通过使用提供的对象字段的反射自动生成单个地图。
通过单一映射,我的意思是整个索引器只有一个映射,它根据字段名称和数据创建一个键(比如将表示字段名称的字符串与数据的字符串表示形式连接起来)。
针对索引器的查找将提供字段名称和数据值,然后在索引器封装的单个映射中查找。
我认为这不一定比类似的解决方案有任何优势,因为索引器由地图映射支持(字段名称映射到数据映射到对象)。
索引器也可以设计为使用注释,以便不是所有字段都被索引,只有那些被适当注释(反之亦然,带注释以排除字段)。
总的来说,地图解决方案的地图让我感觉更轻松,因为它削减了复杂键组装的步骤(对于某些字段数据类型可能会很复杂)。在任何一种情况下,将其全部封装在自动生成其地图的Indexer
中似乎是可行的方法。
<强>更新强>
为Indexer
类型类创建了一个快速的非泛化概念证明(使用map map方法)。 这绝不是完成的工作,但说明了上述概念。一个主要的缺点是依赖bean,因此没有访问器方法的公共和私有字段对于这个索引器是不可见的。
public class Indexer
{
private Map<String,Map<Object,Set<Object>>> index = new HashMap<String,Map<Object,Set<Object>>>();
// Add an object to the index, all properties are indexed.
public void add(Object object) throws Exception
{
BeanInfo info = Introspector.getBeanInfo(object.getClass());
PropertyDescriptor[] propertyDescriptors = info.getPropertyDescriptors();
for (PropertyDescriptor descriptor : propertyDescriptors)
{
String fieldName = descriptor.getName();
Map<Object,Set<Object>> map = index.get(fieldName);
if (map == null)
{
map = new HashMap<Object,Set<Object>>();
index.put(fieldName, map);
}
Method method = descriptor.getReadMethod();
Object data = method.invoke(object);
Set<Object> set = map.get(data);
if (set == null)
{
set = new HashSet<Object>();
map.put(data, set);
}
set.add(object);
}
}
// Retrieve the set of all objects from the index whose property matches the supplied.
public Set<Object> get(String fieldName, Object value)
{
Map<Object,Set<Object>> map = index.get(fieldName);
if (map != null)
{
Set<Object> set = map.get(value);
if (set != null)
{
return Collections.unmodifiableSet(set);
}
}
return null;
}
}