7

我需要一张地图,其中我的密钥应该基于 3 列,比如C1, C2, C3. C1具有最高优先级。C2小于 1C1C3小于 1 C2

我如何在地图中创建键,以便如果有人要求提供有关 的信息C1,我应该能够提供所有具有的值C1。如果要求,我也应该能够返回所有值C1 & C2

4

8 回答 8

2

使用三张地图。

One Map<C1, V> and one Map<C2, V> and one Map<C3, V>. 

您可以将三个映射包装到一个类中并实现您的方法。

于 2013-03-21T06:05:31.493 回答
2

您可以使用与数据库中的多列索引相同的策略,如果您的键列可以排序(即,在 Java 中,它们必须是Comparable)并且可以轻松地为除第一个之外的所有列定义最大值和最小值。

整数列的示例:

public class Key implements Comparable<Key> {
    int c1, c2, c3;

    private static final int c2_min = Integer.MIN_VALUE;
    private static final int c2_max = Integer.MAX_VALUE;
    private static final int c3_min = Integer.MIN_VALUE;
    private static final int c3_max = Integer.MAX_VALUE;

    @Override
    public int compareTo(Key o) {
        if (c1!=o.c1) return Integer.compare(c1, o.c1);
        if (c2!=o.c2) return Integer.compare(c2, o.c2);
        return Integer.compare(c3, o.c3);
    }

    // constructor, equals, ...

}

然后您可以像这样获取某些值k1的所有条目c1

map.subMap(new Key(k1, Key.c2_min, 0), new Key(k1, Key.c2_max, 0));

同样,使用前两列:

map.subMap(new Key(k1, k2, Key.c3_min), new Key(k1, k2, Key.c3_max));
于 2013-03-21T09:13:20.243 回答
0

我认为“优先级”是指通常称为主键、辅助键和第三键的内容。

如果它们都是字符串字段,请将它们连接成一个字符串并将其用作键。在您的情况下,键是 C1+C2+C3 (其中“+”指的是字符串连接)。

于 2013-03-21T06:05:16.570 回答
0

Map 总是只返回一个键的值。您不能让它根据您的关键类内容返回多个值。

简单的方法是为每种键类型保留一个单独的映射,并根据传递的键返回适当的结果。

于 2013-03-21T06:08:13.367 回答
0

可以使用更高级别的键来访问所有较低级别的键和对象的三级索引将需要三级映射。

class ThreeLevelMap<K1,K2,K3,V>
{
    private Map<K1,Map<K2,Map<K3,V>>> store = new HashMap<K,Map<K2,Map<K3,V>>>();
    ...
    public V put(K1 key1, K2 key2, K3 key3, V value) { ... }
    public V get(K1 key1, K2 key2, K3 key3) { ... }

    public static class TLMEntry<K1,K2,K3,V>
    {
    ...
    }
    public Collection<TLMEntry<K1,K2,K3,V>> get(K1 key1, K2 key2) { ... }
    public Collection<TLMEntry<K1,K2,K3,V>> get(K1 key1) { ... }
}

这是一个基本的骨架,但应该让你朝着正确的方向前进。

于 2013-03-21T06:24:32.847 回答
0

这似乎更像是一个数据库问题。如果您的数据库具有如下结构的表:

CREATE TABLE MyMap (
    id IDENTITY PRIMARY KEY,
    c1 int, -- Change data types as needed.
    c2 int,
    c3 int,
    v  int);

那么您只需针对它发出 SELECT 语句。您可能想要使用任何内存中的 Java 数据库。

如果您不想这样做,您可以通过编写容器类值类来纯粹在 Java 中完成等效功能:

class Cdata {
    private int c1;
    private int c2;
    private int c3;
    private int v;
    // Constructors and getters elided.
    public boolean match(int c1) {
        return this.c1 == c1;
    }
    public boolean match(int c1, int c2) {
        return match(c1) && this.c2 == c2;
    }
    public boolean match(int c1, int c2, int c3) {
        return match(c1, c2) && this.c3 == c3;
    }
}

然后创建一个 List 并使用带有过滤器方法的函数式编程库。或者,等待 Java 8 lambda。使用 aMap<Integer, Map<Integer, Map<Integer, Integer>>>>太混乱了。

于 2013-03-21T06:34:00.297 回答
0

您可以使用 TreeMap 来实现您的用例。我假设以下内容:您的三列映射到 3 个递增的整数值,即

C1 = 1, C2 = 2, C3 =3

其中 C1 = 1 是最高优先级,C2 = 2 是下一个,依此类推。

注意:您的键不必总是整数,如果您为Comparator您的TreeMap.

有了这个,您可以执行以下操作:

TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>();
treeMap.put(1, "One");
treeMap.put(2, "two");
treeMap.put(3, "three");

List<String> list = getMappedValues(treeMap, 1);// returns One, Two, Three
//List<String> list = getMappedValues(treeMap, 2);// returns Two, Three
//List<String> list = getMappedValues(treeMap, 3);// returns Three
//List<String> list = getMappedValues(treeMap, 4);// returns null
if(list != null){
    //do something with the list of values
}

private static List<String> getMappedValues(TreeMap<Integer, String> map, Integer key) {
    Entry<Integer, String> e = map.ceilingEntry(key);
    if(e == null){
        return null;
    }
    List<String> list = new ArrayList<String>();
    while(e != null){
        list.add(e.getValue());
        key = e.getKey();
        e = map.higherEntry(key);
    }
    return list;
}
于 2013-03-21T07:55:32.270 回答
0

private class C {

    public C() {
        Map <Object ,String> ObjectC =new HashMap<Object, String>();
    }
}

private class B {

    public B() {
        Map <Object ,C> ObjectB =new HashMap<Object, C>();
    }
}

private class A {

    public A() {
        Map <Object ,B> ObjectA =new HashMap<Object, B>();
    }
}

所以这可以向你保证一个漂亮的结构,你不需要做更多的工作,因为你可以获得 A 的所有内容

MapVar.ObjectA.get(C1);

如果同时给出 C1, C2 你可以调用

MapVar.ObjectA.get(C1).ObjectB.get(C2);

如果同时给出 C1, C2 , C3 你可以调用

MapVar.ObjectA.get(C1).ObjectB.get(C2).ObjectC.get(C3);;

然后您可以简单地遍历地图并获取值。

于 2013-03-29T08:54:53.753 回答