2017-04-07 53 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());