2017-04-07 37 views
3

列出我想要一个Map几个名单,他们每个人Comparable对象组成的,但并不总是相同的,所以有可能是一个DoublesListStrings一个List,等...通用地图与可比

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

不幸的是,Map如上所定义,因为在每个List元件不能相比不会是有用的。因此,我不得不欺骗和引入类型参数到类:

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

这并不完全正确,因为不是所有的列表是相同类型的。但它是有效的,我必须做的唯一事情就是当我将Double添加到双列表或String到字符串列表中时,将类型转换为T。我确保每种类型都只添加到正确类型的列表中。

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

另一种方法是对每种类型的List都有一个Map。但是这只会使代码更丑,我只能对列表进行排序并将它们作为字符串值插入到数据库中,因此我只能在可比较对象上调用toString

+1

您可以使用['checkedList'](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#checkedList-java.util.List- java.lang.Class-)来减少错误的风险。 – shmosel

+2

由于您无法静态地告诉Java编译器“List”中元素的类型,您甚至不能确保其中一个列表中的元素可以相互比较。总之,你应该不这样做,或者接受你绕过静态类型检查,例如通过声明它为'Map >',使用原始泛型类型'Comparable'。然后接受编译器警告,告诉您您正在绕过静态类型检查。 – Andreas

+0

@shmosel哇,我怎么从来没有听说过这个?谢谢:) – Roland

回答

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]

0

从它说docs of java generic wildcard:(?)

在通用代码,问号,称为通配符,表示未知类型

而且也:

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

所以,如果你有以下声明:

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

那么你就不能添加任何list,因为你只是告诉编译器说:“我不知道对象的类型,这会要放在list

所以,你的代码List<Comparable<?>>意味着,‘我想包含类似的对象名单,但我不知道它的类型’,这是不是编译OK,因为编译器需要知道它的工作类型信息。

要使用列表中包含的任何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感兴趣,希望这可以对你有所帮助。

+0

你在那里有罕见的类型。这将导致更多的SO问题... –

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());