2013-02-18 16 views
14

Potrzebuję do iteracji nad zestawem wejściowym mapy, od którego nie znam jego sparametryzowanych typów.Powtórzenie zestawu pozycji mapy

Podczas powtarzania takiego zestawu pytań, dlaczego to się nie kompiluje?

public void myMethod(Map anyMap) { 
    for(Entry entry : anyMap.entrySet()) { 
     ... 
    } 
} 

ale kompilacji:

public void myMethod(Map anyMap) { 
    Set<Entry> entries = anyMap.entrySet(); 
    for(Entry entry : entries) { 
     ... 
    } 
} 

i ten zestawia również (nie mogę użyć tego jednego, ponieważ nie wiem rodzaje mapie):

public void myMethod(Map<String, String> stringMap) { 
    for(Entry<String,String> entry : stringMap.entrySet()) { 
     ... 
    } 
} 
+0

sprawdzić swoją nazwę zmiennej – Renjith

+0

nawet drugi urywek kodu nie powinien skompilować. Nazwy zmiennych są różne. Jesteś pewien, że to skompilowane? Opublikuj skompilowany kod następnie. Nie wpisuj tego samodzielnie – SudoRahul

+0

thnaks @Renjith, poprawiono nazwę zmiennej – Sergio

Odpowiedz

20

błąd dostać w pierwszym z nich jest:

Type mismatch: cannot convert from element type Object to Map.Entry 

To dlatego, że kompilator konwertuje pętli for-in:

for (Entry entry : anyMap.entrySet()) { 
} 

Do:

for (Iterator i = anyMap.entrySet().iterator(); i.hasNext();) { 
    Entry e = i.next(); // not allowed 
} 

Twój drugi przykład działa, , ale tylko przez oszustwo! Wykonujesz niezaznaczoną obsadę, aby uzyskać Setpowrót do Set<Entry>.

Set<Entry> entries = anyMap.entrySet(); // you get a compiler warning here 
for (Entry entry : entries) { 
} 

Staje:

Set<Entry> entries = anyMap.entrySet(); 
for (Iterator<Entry> i = entries.iterator(); i.hasNext();) { 
    Entry e = (Entry) i.next(); // allowed 
} 

Aktualizacja

Jak wspomniano w komentarzach, informacje typu jest zagubienie w obu przykładach: z powodu surowych typu zasad Erasure kompilator za.

Aby zapewnić wsteczną kompatybilność, WSZYSTKIE metody instancji typu surowców są zastępowane przez ich usunięte odpowiedników. Tak więc, ponieważ twój Map jest typu surowego, wszystko zostanie usunięte. W tym jego metoda Set<Map.Entry<K, V>> entrySet();: Twoja instancja typu surowego będzie zmuszona do użycia skasowanej wersji: Set entrySet().

+0

+1 To jest właściwa odpowiedź. –

+0

, ale dlaczego w pierwszym przypadku "anyMap.entrySet(). Iterator()" nie zwraca "Iterator "?. Wartością zwracaną przez "entrySet()" jest "Set >", więc iterator tego zestawu powinien być sparametryzowany za pomocą "Entry", nawet jeśli nie podano typów Key i Value, prawda? – Sergio

+0

@Sergio jest to prawdopodobnie dlatego, że przekonwertowany Iterator nie używa generycznych. –

1

pierwszy kod Snippet nie będzie kompilować, ponieważ zmienna map nie istnieje. Nazwałeś parametr anyMap ale próbował uzyskać dostęp go jako map, naprawić i kod zostanie skompilowany oprócz niektórych rawtypes ostrzeżeń

+1

Nie, to nie jest właściwe. –

+0

@BlankChisui. Zakładając, że nazwa mapy była literówka. Problem nadal będzie tym, o czym wspomniał OP. To nie jest kwestia złego imienia. –

+0

Tak, nazwa mapy była literówka, poprawione już, przepraszam – Sergio

2

W pierwszym przykładzie map.entrySet() zwraca Set, podczas iteracji w pętli używany jest Iterator. Nie ma informacji o ustawionym typie zawartości, więc Java używa Object jako Object jest typem podstawowym, a kompilator mówi, że nie może przekonwertować Object to Entry.

Set<Map.Entry<K, V>> entrySet(); 

Gdy używasz surowego typu mapy, entrySet zwraca tylko Ustaw, bez informacji o typie.

W drugim przykładzie należy ręcznie przekonwertować zestaw na zestaw < Entry> (z ostrzeżeniem). Teraz Java wie, co jest w środku. Możesz więc iterować.

W ostatnim przykładzie znasz typ mapy, więc entrySet zwraca poprawnie wpisany zestaw i możesz wykonywać iteracje bez żadnych konwencji typów.

4

To dlatego, że używasz surowego typu Mapa, dlatego map.entrySet() dostanie ci zestaw nieparametryczny, który w zamian daje Obiekt w iteracji, a nie Wpis.

Prostym, ale eleganckim rozwiązaniem jest użycie mapy < ?,? >, który nadal będzie można przekazać żadnej mapie, ale z drugiej wymusza ręczne map.entrySet(), aby mieć wartość zwracaną Set <Entry>:

public void test(Map<?,?> map) {   
    for(Entry e : map.entrySet()){ 
     Object key = e.getKey(); 
     Object value = e.getValue(); 
    }  
} 
+0

, ale jeśli wartością zwracaną przez "entrySet()" jest "Set >, dlaczego wynikowy zestaw nie jest sparametryzowany za pomocą" Map.Entry ", nawet jeśli nie podano typów Key i Value? – Sergio

-1

Mam wobec tego samego problemu. Wygląda na to, że odlewanie to problem. Wypróbowałem poniższy kod i działało.

for(Object entry : hashMap.entrySet()) 
    { 
     System.out.println(((Entry<Object, Object>) entry).getKey() + " = " + ((Entry<Object, Object>) entry).getValue()); 

    } 
+0

Nie używaj w pierwszym rzędzie typów surowych, a wtedy możesz uniknąć takiego nieprzyjemnego kodu. – Tom

0

dostajesz rrror czasie kompilacji, ponieważ nie jesteś z określeniem rodzaju w HashMap

Jak

HashMap <(Integer,String> hm=new HashMap<(Integer,String>(); 

Jeśli określił jako Integer i String, ty nie uzyskać błąd czasu kompilacji.

jeśli nie wiesz, którego wartość ma zamiar dodać w swoim HashMap następnie użyć

HashMap<(Object,Object> hm=new HashMap(); 
Powiązane problemy