1

假设我有一个简单的 Java 对象,我们称之为 DefinedData。它将包含许多不同类型的最终字段,例如字符串、整数、枚举,甚至可能是一组或两个字符串。总而言之,它只是一个相对简单的数据容器。其中可能有 1k 到 2k 个,所有静态最终对象。这些字段中的大多数将是唯一的,因为没有其他 DefinedData 对象对该字段具有相同的值。

这些将被放置到 (DefinedData, Object) 的 Map 中。现在,如果您有 DefinedData 对象,您可以轻松地将该对象从 Map 中取出,但如果您只有一个唯一字段值怎么办?您不能只将其传递给地图。您必须遍历键并检查,这意味着使用 DefinedData 中每个字段的查找方法包装地图。可行,但不是最漂亮的东西,特别是如果 Map 中有很多值和很多查找,这是可能的。要么是这样,要么需要查找 DefinedData 对象,这又是一堆地图......

这几乎听起来像是数据库的工作(根据任何列查找),但这不是解决这个特定问题的好方法。我还宁愿避免使用十几个不同的 Map,每个 Map 都将一个字段从 DefinedData 映射到 Object。我见过的多键映射不适用,因为它们需要所有键值,而不仅仅是一个。是否有可以处理此特定问题的 Map、Collections 或其他实现?

4

2 回答 2

0

避免拥有多个映射的唯一方法是以某种方式遍历所有 DefinedData 对象。原因是,在提出请求之前,您无法知道如何将它们分开或排序。

如果你有一桶苹果,可以举个例子。在任何时候,有人可能会上来要求某种颜色、某种种类或某种尺寸。您必须选择按其中一个类别进行排序,并且必须在所有苹果中搜索其他类别。如果你能拥有三套相同的苹果;每个类别一个。

拥有多个映射将是一个更快的解决方案,尽管会占用更多内存,而迭代会更容易实现、速度更慢并且使用更少的内存。

于 2013-11-18T23:06:35.830 回答
0

我不愿提出这个建议,但是您可以将查找封装在某种Indexer类后面,该类使用提供的对象的字段通过反射自动生成单个映射。

通过单个映射,我的意思是整个索引器只有一个映射,它基于字段名称和数据创建一个键(例如将表示字段名称的字符串与数据的字符串表示连接起来)。

针对索引器的查找将提供字段名称和数据值,然后将在索引器封装的单个映射中进行查找。

我认为这与索引器由映射映射(字段名称映射到数据到对象映射)支持的类似解决方案相比不一定有任何优势。

索引器还可以设计为使用注释,以便并非所有字段都被索引,只有那些适当注释的字段(反之亦然,带有注释以排除字段)。

总体而言,地图解决方案的地图让我印象深刻,因为它省去了复杂的密钥组装步骤(这对于某些字段数据类型可能很复杂)。在任何一种情况下,将其全部封装在Indexer自动生成其地图的方法中似乎是要走的路。

更新:

为类型类制作了一个快速的非通用概念证明Indexer(使用 map of maps 方法)。 这绝不是完成的工作,而是说明了上述概念。一个主要缺陷是对 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;
    }
}
于 2013-11-18T23:52:38.407 回答