具有可比较列表的通用地图

时间:2017-04-07 05:47:12

标签: java generics collections

我希望Map包含多个列表,每个列表由Comparable个对象组成,但并不总是相同,因此可能会有ListDoubles和一个List Strings等等......

Map<String, List<Comparable<?>>>

不幸的是,上面定义的Map没有用,因为无法比较每个List中的元素。因此我不得不作弊并在课堂上引入一个类型参数:

class MyClass<T extends Comparable<? super T>> {
    Map<String, List<T>> myMap;
}

这并不完全正确,因为并非所有列表都属于同一类型。但它有效,我唯一需要做的就是当我将T添加到双打列表或Double到字符串列表时,对String进行类型转换。我确保每种类型只添加到正确类型的列表中。

有没有更好的方法来解决这个问题?

替代方法是为每种类型的Map设置一个List。但这只会使代码变得更加丑陋,而我对列表所做的唯一事情就是对它们进行排序并将它们作为String值插入到DB中,因此我只在可比较对象上调用toString

3 个答案:

答案 0 :(得分:1)

您可以使用List<Object>使其成为通用的此目的。
您可能希望对列表中的某些特定数据类型执行instance of检查。

Map<String, List<Object>> map = new HashMap<>();

List<Object> list;

list = new ArrayList<>(Arrays.asList(new Object[] { 1, 2, 3.45, "dev", 'A', true, false }));
map.put("key1", list);

list = new ArrayList<>(Arrays.asList(new Object[] { false, 100, 5.1234f, "user", 'Z', true }));
map.put("key2", list);

for (Map.Entry<String, List<Object>> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " => " + entry.getValue());
}

输出:
key1 => [1, 2, 3.45, dev, A, true, false] key2 => [false, 100, 5.1234, user, Z, true]

答案 1 :(得分:0)

来自docs of java generic wildcard它说:

  

在通用代码中,称为通配符的问号(?)表示未知类型

还有:

  

通配符从不用作泛型方法调用,泛型类实例创建或超类型的类型参数。

因此,如果您有以下声明:

List<?> list = new ArrayList<>();

然后你不能向list添加任何内容,因为你刚刚告诉编译器“我不知道将放入list的对象类型”

所以你的代码List<Comparable<?>>意味着“我希望列表包含可比较的对象,但我不知道它的类型”,这对于编译器来说是不行的,因为编译器确实需要知道类型信息为了它的工作。

要使用列表包含任何Comparable个对象,您可以使用upper bounded wildcards之类的:

Map<String, List<? extends Comparable>> map = new HashMap<>();

然后您可以将任何comparable列表作为此地图的值:

public static void main(String[] args) {
    Map<String, List<? extends Comparable>> map = new HashMap<>();
    List<Integer> as = new ArrayList<>();
    as.add(1);
    as.add(5);
    as.add(3);

    map.put("as", as);

    List<String> bs = new ArrayList<>();
    bs.add("hello");
    bs.add("world");
    bs.add("generics");

    map.put("bs", bs);
}

最后我想你会对inheritance and subtypes in generics感兴趣,希望这对你有所帮助。

答案 2 :(得分:0)

这看起来有点像异构地图。除了比较它们之外,你实际上对你的可比对象列表做了什么?

但是,如果您希望列表具有不同的类型,则间接应该在List附近。

public final class SortableList<T extends Comparable<? super T>> {
    private final List<T> elements;
    public SortableList(List<T> elements) {
        this.elements = elements;
    }
    public List<T> elements() {
        return elements;
    }
}

...

Map<String,SortableList<?>> sortables;
...
Comparable<?> colaMax = Collections.max(sortables.get("shirley").elements());