Map
Java'da arabirimi uygulayan bir nesnem varsa ve içindeki her çift üzerinde yineleme yapmak istiyorsam, haritadan geçmenin en etkili yolu nedir?
Elemanların sıralaması arayüz için sahip olduğum harita uygulamasına bağlı olacak mı?
Map
Java'da arabirimi uygulayan bir nesnem varsa ve içindeki her çift üzerinde yineleme yapmak istiyorsam, haritadan geçmenin en etkili yolu nedir?
Elemanların sıralaması arayüz için sahip olduğum harita uygulamasına bağlı olacak mı?
Yanıtlar:
Map<String, String> map = ...
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "/" + entry.getValue());
}
remove
yöntemini çağırmanız gerektiğidir . Bu durumda, bu diğer cevap size nasıl yapılacağını gösterir. Aksi takdirde, yukarıdaki cevapta gösterildiği gibi gelişmiş döngü gitmenin yoludur.
map.values()
veya map.keySet()
yalnızca değerler veya anahtarlar arasında geçiş yapmak istediğinizi unutmayın.
Diğer cevapları özetlemek ve bildiklerimle birleştirmek için bunu yapmanın 10 ana yolunu buldum (aşağıya bakınız). Ayrıca, bazı performans testleri yazdım (aşağıdaki sonuçlara bakın). Örneğin, bir haritanın tüm anahtarlarının ve değerlerinin toplamını bulmak istiyorsak şunu yazabiliriz:
Yineleyici ve Harita'yı kullanma
long i = 0;
Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, Integer> pair = it.next();
i += pair.getKey() + pair.getValue();
}
Kullanılması foreach ve Map.Entry
long i = 0;
for (Map.Entry<Integer, Integer> pair : map.entrySet()) {
i += pair.getKey() + pair.getValue();
}
Java 8'den forEach kullanma
final long[] i = {0};
map.forEach((k, v) -> i[0] += k + v);
KeySet ve foreach öğelerini kullanma
long i = 0;
for (Integer key : map.keySet()) {
i += key + map.get(key);
}
KeySet ve yineleyiciyi kullanma
long i = 0;
Iterator<Integer> itr2 = map.keySet().iterator();
while (itr2.hasNext()) {
Integer key = itr2.next();
i += key + map.get(key);
}
Kullanılması için ve Map.Entry
long i = 0;
for (Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator(); entries.hasNext(); ) {
Map.Entry<Integer, Integer> entry = entries.next();
i += entry.getKey() + entry.getValue();
}
Java 8 Stream API'sini kullanma
final long[] i = {0};
map.entrySet().stream().forEach(e -> i[0] += e.getKey() + e.getValue());
Java 8 Stream API'yi paralel kullanma
final long[] i = {0};
map.entrySet().stream().parallel().forEach(e -> i[0] += e.getKey() + e.getValue());
Kullanılması IterableMap arasındaApache Collections
long i = 0;
MapIterator<Integer, Integer> it = iterableMap.mapIterator();
while (it.hasNext()) {
i += it.next() + it.getValue();
}
Eclipse (CS) koleksiyonlarının MutableMap kullanma
final long[] i = {0};
mutableMap.forEachKeyValue((key, value) -> {
i[0] += key + value;
});
Performans testleri (mod = AverageTime, sistem = Windows 8.1 64 bit, Intel i7-4790 3.60 GHz, 16 GB)
Küçük bir harita (100 element) için 0.308 puanı en iyisidir
Benchmark Mode Cnt Score Error Units
test3_UsingForEachAndJava8 avgt 10 0.308 ± 0.021 µs/op
test10_UsingEclipseMap avgt 10 0.309 ± 0.009 µs/op
test1_UsingWhileAndMapEntry avgt 10 0.380 ± 0.014 µs/op
test6_UsingForAndIterator avgt 10 0.387 ± 0.016 µs/op
test2_UsingForEachAndMapEntry avgt 10 0.391 ± 0.023 µs/op
test7_UsingJava8StreamApi avgt 10 0.510 ± 0.014 µs/op
test9_UsingApacheIterableMap avgt 10 0.524 ± 0.008 µs/op
test4_UsingKeySetAndForEach avgt 10 0.816 ± 0.026 µs/op
test5_UsingKeySetAndIterator avgt 10 0.863 ± 0.025 µs/op
test8_UsingJava8StreamApiParallel avgt 10 5.552 ± 0.185 µs/op
10000 elementli bir harita için 37.606 puanı en iyisidir
Benchmark Mode Cnt Score Error Units
test10_UsingEclipseMap avgt 10 37.606 ± 0.790 µs/op
test3_UsingForEachAndJava8 avgt 10 50.368 ± 0.887 µs/op
test6_UsingForAndIterator avgt 10 50.332 ± 0.507 µs/op
test2_UsingForEachAndMapEntry avgt 10 51.406 ± 1.032 µs/op
test1_UsingWhileAndMapEntry avgt 10 52.538 ± 2.431 µs/op
test7_UsingJava8StreamApi avgt 10 54.464 ± 0.712 µs/op
test4_UsingKeySetAndForEach avgt 10 79.016 ± 25.345 µs/op
test5_UsingKeySetAndIterator avgt 10 91.105 ± 10.220 µs/op
test8_UsingJava8StreamApiParallel avgt 10 112.511 ± 0.365 µs/op
test9_UsingApacheIterableMap avgt 10 125.714 ± 1.935 µs/op
100000 elementli bir harita için skor 1184.767 en iyisidir
Benchmark Mode Cnt Score Error Units
test1_UsingWhileAndMapEntry avgt 10 1184.767 ± 332.968 µs/op
test10_UsingEclipseMap avgt 10 1191.735 ± 304.273 µs/op
test2_UsingForEachAndMapEntry avgt 10 1205.815 ± 366.043 µs/op
test6_UsingForAndIterator avgt 10 1206.873 ± 367.272 µs/op
test8_UsingJava8StreamApiParallel avgt 10 1485.895 ± 233.143 µs/op
test5_UsingKeySetAndIterator avgt 10 1540.281 ± 357.497 µs/op
test4_UsingKeySetAndForEach avgt 10 1593.342 ± 294.417 µs/op
test3_UsingForEachAndJava8 avgt 10 1666.296 ± 126.443 µs/op
test7_UsingJava8StreamApi avgt 10 1706.676 ± 436.867 µs/op
test9_UsingApacheIterableMap avgt 10 3289.866 ± 1445.564 µs/op
Grafikler (harita boyutuna bağlı olarak performans testleri)
Tablo (harita boyutuna bağlı olarak performans testleri)
100 600 1100 1600 2100
test10 0.333 1.631 2.752 5.937 8.024
test3 0.309 1.971 4.147 8.147 10.473
test6 0.372 2.190 4.470 8.322 10.531
test1 0.405 2.237 4.616 8.645 10.707
test2 0.376 2.267 4.809 8.403 10.910
test7 0.473 2.448 5.668 9.790 12.125
test9 0.565 2.830 5.952 13.220 16.965
test4 0.808 5.012 8.813 13.939 17.407
test5 0.810 5.104 8.533 14.064 17.422
test8 5.173 12.499 17.351 24.671 30.403
Tüm testler GitHub'da .
long sum = 0; map.forEach( /* accumulate in variable sum*/);
yakalar, örneğin sum
söyleyenden daha yavaş olabilir stream.mapToInt(/*whatever*/).sum
. tezgaha.
AtomicInteger
Sorunu çözmek için değiştirin .
x±e
gelen aralığı içinde bir sonuç olduğunu ima x-e
için x+e
(en hızlı sonuç, yani 1184.767±332.968
arasında değişir) 852
için 1518
, ikinci yavaş (oysa 1706.676±436.867
) arasında çalışan 1270
ve 2144
, sonuç yani hala örtüşme anlamlı. Şimdi, en yavaş sonuca bakın 3289.866±1445.564
, bu da 1844
ve birbirinden ayrılma anlamına geliyor ve bu test sonuçlarının anlamsız 4735
olduğunu biliyorsunuz .
while
Bir for
döngüye karşı bir döngü kullanmak , yineleme için farklı bir teknik değildir. Ve testlerinizde aralarında böyle bir varyasyona sahip olduklarına şaşırdım - bu, testlerin test etmeyi planladığınız şeylerle ilgili olmayan dış faktörlerden düzgün bir şekilde izole edilmediğini gösterir.
Java 8'de yeni lambdas özelliklerini kullanarak temiz ve hızlı bir şekilde yapabilirsiniz:
Map<String,String> map = new HashMap<>();
map.put("SomeKey", "SomeValue");
map.forEach( (k,v) -> [do something with key and value] );
// such as
map.forEach( (k,v) -> System.out.println("Key: " + k + ": Value: " + v));
Derleyicinin türü k
ve v
çıkarımı yapılacaktır ve kullanmaya gerek yokturMap.Entry
artık.
Çantada keklik!
map.entrySet().stream()
docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
Evet, sipariş belirli Harita uygulamasına bağlıdır.
@ ScArcher2 daha zarif Java 1.5 sözdizimine sahiptir . 1.4'te böyle bir şey yapardım:
Iterator entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
Entry thisEntry = (Entry) entries.next();
Object key = thisEntry.getKey();
Object value = thisEntry.getValue();
// ...
}
for
olarak yapı for (Entry e : myMap.entrySet)
sen koleksiyonunu değiştirmesine izin vermez, ama @HanuAthena olarak örnek size verir çünkü, çalışması gerekir belirtilen Iterator
kapsamda. (Bir şeyi kaçırmadıkça ...)
Entry thisEntry = (Entry) entries.next();
: tanımıyor Entry
. Bu sahte kod başka bir şey için mi?
java.util.Map.Entry
.
Bir harita üzerinden yineleme yapmak için tipik kod:
Map<String,Thing> map = ...;
for (Map.Entry<String,Thing> entry : map.entrySet()) {
String key = entry.getKey();
Thing thing = entry.getValue();
...
}
HashMap
kanonik harita uygulamasıdır ve garanti vermez (veya üzerinde herhangi bir mutasyon işlemi yapılmazsa düzeni değiştirmemelidir). SortedMap
anahtarların doğal sırasına göre girişleri veya Comparator
sağlanmışsa a döndürür . LinkedHashMap
nasıl oluşturulduğuna bağlı olarak girişleri ekleme veya erişim sırasına göre döndürür. EnumMap
girişleri doğal tuş sırasına göre döndürür.
(Güncelleme: Bunun artık doğru olmadığını düşünüyorum. ) Not, IdentityHashMap
entrySet
yineleyici şu anda Map.Entry
her öğede aynı örneği döndüren tuhaf bir uygulamaya sahip entrySet
! Ancak, yeni bir yineleyici her geliştiğinde Map.Entry
güncellenir.
LinkedHashMap
. Bunlar sayesinde iterator
, spliterator
, entrySet
vb sırasını değiştirmez.
Yineleyici ve jenerikler kullanma örneği:
Iterator<Map.Entry<String, String>> entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, String> entry = entries.next();
String key = entry.getKey();
String value = entry.getValue();
// ...
}
Iterator
Kapsamını sınırlamak için bir for döngüsü koymalısınız .
for (Iterator<Map.Entry<K, V>> entries = myMap.entrySet().iterator(); entries.hasNext(); ) { Map.Entry<K, V> entry = entries.next(); }
. Bu yapıyı kullanarak (değişkenin görünürlüğü) entries
kapsamını for döngüsüyle sınırlandırırız .
Bu iki bölümlü bir soru:
Bir Harita'nın girişleri üzerinde nasıl yinelenir - @ ScArcher2 bunu mükemmel bir şekilde yanıtladı .
Yineleme sırası nedir - sadece kullanıyorsanız Map
, sonra kesinlikle konuşursanız, sipariş garantisi yoktur . Bu nedenle, herhangi bir uygulamanın verdiği sıralamaya gerçekten güvenmemelisiniz. Ancak, SortedMap
arayüz Map
tam olarak aradığınızı genişletir ve sağlar - uygulamalar her zaman tutarlı bir sıralama düzeni sağlar.
NavigableMap
başka bir yararlı uzantıdır - bu, SortedMap
anahtar kümesindeki sıralı konumlarına göre girişleri bulmak için ek yöntemlerle birdir. Yani potansiyel olarak bu ilk etapta yineleme ihtiyacını kaldırabilir - Eğer özgü bulmak mümkün olabilir entry
kullandığınız peşinde higherEntry
, lowerEntry
, ceilingEntry
, veya floorEntry
yöntemler. descendingMap
Yöntem bile size açık bir yöntem verir geçişi sırasını tersine çevirmek .
Harita üzerinde yineleme yapmanın birkaç yolu vardır.
Harita üzerinde bir milyon anahtar / değer çifti saklayarak harita üzerinde depolanan ortak bir veri seti için performanslarının karşılaştırılması ve harita üzerinde yinelenmesi.
1) entrySet()
Her döngü için
for (Map.Entry<String,Integer> entry : testMap.entrySet()) {
entry.getKey();
entry.getValue();
}
50 milisaniye
2) keySet()
Her döngü için
for (String key : testMap.keySet()) {
testMap.get(key);
}
76 milisaniye
3) kullanma entrySet()
ve yineleyici
Iterator<Map.Entry<String,Integer>> itr1 = testMap.entrySet().iterator();
while(itr1.hasNext()) {
Map.Entry<String,Integer> entry = itr1.next();
entry.getKey();
entry.getValue();
}
50 milisaniye
4) kullanma keySet()
ve yineleyici
Iterator itr2 = testMap.keySet().iterator();
while(itr2.hasNext()) {
String key = itr2.next();
testMap.get(key);
}
75 milisaniye
Referans verdim this link
.
Bunu yapmanın doğru yolu, kabul edilen cevabı en verimli olduğu şekilde kullanmaktır. Aşağıdaki kodu biraz daha temiz görünüyor.
for (String key: map.keySet()) {
System.out.println(key + "/" + map.get(key));
}
O(1) = 2*O(1)
büyük O gösteriminin tanımıdır. Biraz daha yavaş çalıştığı için haklısınız, ancak karmaşıklık açısından aynılar.
2
entrySet()
keySet()
Map
2
İle Java 8 , Harita forEach ve lambda ifadesi kullanarak yineleme yapabilirsiniz,
map.forEach((k, v) -> System.out.println((k + ":" + v)));
İle Eclipse Koleksiyonları şunları kullanırsınız forEachKeyValue
üzerinde yöntemi MapIterable
ile devralınan arayüzü MutableMap
ve ImmutableMap
arayüzleri ve bunların uygulamaları.
MutableBag<String> result = Bags.mutable.empty();
MutableMap<Integer, String> map = Maps.mutable.of(1, "One", 2, "Two", 3, "Three");
map.forEachKeyValue((key, value) -> result.add(key + value));
Assert.assertEquals(Bags.mutable.of("1One", "2Two", "3Three"), result);
Anonim bir iç sınıf kullanarak, kodu aşağıdaki gibi yazabilirsiniz:
final MutableBag<String> result = Bags.mutable.empty();
MutableMap<Integer, String> map = Maps.mutable.of(1, "One", 2, "Two", 3, "Three");
map.forEachKeyValue(new Procedure2<Integer, String>()
{
public void value(Integer key, String value)
{
result.add(key + value);
}
});
Assert.assertEquals(Bags.mutable.of("1One", "2Two", "3Three"), result);
Not: Eclipse Collections için bir komisyoncuyum.
Lambda İfade Java 8
Java 1.8'de (Java 8) , Yinelenebilir Arabirimdeki yineleyicilere benzeyen Toplama işlemlerinden ( Akış işlemleri ) forEach yöntemi kullanılarak bu çok daha kolay hale geldi .
Sadece koduna açıklamada altında yapıştırın ve yeniden adlandırmak kopya HashMap değişkeni hm anahtar-değer çifti dışarı yazdırmak için HashMap değişkene.
HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();
/*
* Logic to put the Key,Value pair in your HashMap hm
*/
// Print the key value pair in one line.
hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));
// Just copy and paste above line to your code.
Aşağıda Lambda Expression kullanarak denedim örnek kod . Bu şeyler çok havalı. Denemek gerekir.
HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
Random rand = new Random(47);
int i = 0;
while(i < 5) {
i++;
int key = rand.nextInt(20);
int value = rand.nextInt(50);
System.out.println("Inserting key: " + key + " Value: " + value);
Integer imap = hm.put(key, value);
if( imap == null) {
System.out.println("Inserted");
} else {
System.out.println("Replaced with " + imap);
}
}
hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));
Output:
Inserting key: 18 Value: 5
Inserted
Inserting key: 13 Value: 11
Inserted
Inserting key: 1 Value: 29
Inserted
Inserting key: 8 Value: 0
Inserted
Inserting key: 2 Value: 7
Inserted
key: 1 value:29
key: 18 value:5
key: 2 value:7
key: 8 value:0
key: 13 value:11
Ayrıca biri için Spliterator kullanabilirsiniz .
Spliterator sit = hm.entrySet().spliterator();
GÜNCELLEME
Oracle Docs belgelerine bağlantılar dahil. Lambda hakkında daha fazla bilgi için bu bağlantıya gidin ve Toplam İşlemleri okumalı ve Ayırıcı için bu bağlantıya gidin .
Teorik olarak, en etkili yol haritanın hangi uygulamasına bağlı olacaktır. Bunu yapmanın resmi yolu , her biri bir anahtar ve bir değer ( ve ) içeren bir map.entrySet()
dizi döndüren çağırmaktır .Map.Entry
entry.getKey()
entry.getValue()
Özyinelemeli bir uygulamada, kullansanız da map.keySet()
, map.entrySet()
başka bir şeyde fark yaratabilir . Ama kimsenin böyle yazmasının bir sebebini düşünemiyorum. Büyük olasılıkla yaptığınız performansla hiçbir fark yaratmaz.
Ve evet, emir uygulamaya bağlıdır - ayrıca (muhtemelen) yerleştirme sırası ve diğer kontrol edilmesi zor faktörler.
valueSet()
Orijinal olarak yazdım ama elbette entrySet()
cevap.
Lambda ifadesiniforEach
kabul eden bir yöntemimiz var . Akış API'larımız da var . Bir haritayı düşünün:
Map<String,String> sample = new HashMap<>();
sample.put("A","Apple");
sample.put("B", "Ball");
Anahtarlar üzerinde yineleme:
sample.keySet().forEach((k) -> System.out.println(k));
Değerler üzerinde yineleme:
sample.values().forEach((v) -> System.out.println(v));
Girişler üzerinde yineleme (forEach ve Streams kullanma):
sample.forEach((k,v) -> System.out.println(k + ":" + v));
sample.entrySet().stream().forEach((entry) -> {
Object currentKey = entry.getKey();
Object currentValue = entry.getValue();
System.out.println(currentKey + ":" + currentValue);
});
Akarsuların avantajı, istediğimiz takdirde kolayca paralelleştirilebilmeleridir. Sadece yukarıdakilerin parallelStream()
yerine kullanmamız gerekiyor stream()
.
forEachOrdered
forEach
akışlarla vs ? forEach
(Tanımlı ise) karşılaşma talimatına uymaya olarak doğada doğal olarak belirli olmayan vermezse forEachOrdered
yok. Bu yüzden forEach
siparişin korunacağını garanti etmez. Ayrıca daha fazlası için bunu kontrol edin .
Java 8:
Lambda ifadelerini kullanabilirsiniz:
myMap.entrySet().stream().forEach((entry) -> {
Object currentKey = entry.getKey();
Object currentValue = entry.getValue();
});
Daha fazla bilgi için bunu takip edin .
myMap.forEach( (currentKey,currentValue) -> /* action */ );
çok daha özlü.
Haritada kişi keys
ve / veya values
ve / veya yineleme both (e.g., entrySet)
ilgilendiğine bağlıdır.
keys -> keySet()
Haritanın içinden tekrarlayın :
Map<String, Object> map = ...;
for (String key : map.keySet()) {
//your Business logic...
}
values -> values()
Haritanın içinden tekrarlayın :
for (Object value : map.values()) {
//your Business logic...
}
both -> entrySet()
Haritanın içinden tekrarlayın :
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
//your Business logic...
}
Dahası, HashMap ile Yinelemenin 3 fark yolu vardır. Onlar aşağıdaki gibidir__
//1.
for (Map.Entry entry : hm.entrySet()) {
System.out.print("key,val: ");
System.out.println(entry.getKey() + "," + entry.getValue());
}
//2.
Iterator iter = hm.keySet().iterator();
while(iter.hasNext()) {
Integer key = (Integer)iter.next();
String val = (String)hm.get(key);
System.out.println("key,val: " + key + "," + val);
}
//3.
Iterator it = hm.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
Integer key = (Integer)entry.getKey();
String val = (String)entry.getValue();
System.out.println("key,val: " + key + "," + val);
}
public class abcd{
public static void main(String[] args)
{
Map<Integer, String> testMap = new HashMap<Integer, String>();
testMap.put(10, "a");
testMap.put(20, "b");
testMap.put(30, "c");
testMap.put(40, "d");
for (Integer key:testMap.keySet()) {
String value=testMap.get(key);
System.out.println(value);
}
}
}
VEYA
public class abcd {
public static void main(String[] args)
{
Map<Integer, String> testMap = new HashMap<Integer, String>();
testMap.put(10, "a");
testMap.put(20, "b");
testMap.put(30, "c");
testMap.put(40, "d");
for (Entry<Integer, String> entry : testMap.entrySet()) {
Integer key=entry.getKey();
String value=entry.getValue();
}
}
}
Java'da Harita arayüzünü uygulayan bir nesnem varsa ve içerdiği her bir çifti yinelemek istersem, haritadan geçmenin en etkili yolu nedir?
Anahtarları döngü etkinliği uygulamanız için bir öncelikse, anahtarları Map
istediğiniz sırada tutan bir uygulama seçin .
Elemanların sıralaması arayüz için sahip olduğum harita uygulamasına bağlı olacak mı?
Evet kesinlikle.
Map
uygulamalar belirli bir yineleme sırası vaat ederken, diğerleri bunu önermez.Map
Anahtar / değer çiftlerinin farklı düzenini korumak için farklı uygulamalar .Map
Java 11 ile birlikte gelen çeşitli uygulamaları özetleyerek oluşturduğum bu tabloya bakın. Özel olarak, yineleme sırası sütununa dikkat edin . Yakınlaştırmak için tıklayın / dokunun.
Bir siparişi koruyan dört Map
uygulama olduğunu görebilirsiniz :
TreeMap
ConcurrentSkipListMap
LinkedHashMap
EnumMap
NavigableMap
arayüzBunlardan ikisi NavigableMap
arayüzü uyguluyor : TreeMap
& ConcurrentSkipListMap
.
Eski SortedMap
arayüz, yeni NavigableMap
arayüz tarafından etkili bir şekilde yerini alır . Ancak, yalnızca eski arayüzü uygulayan üçüncü taraf uygulamaları bulabilirsiniz.
Map
Çiftlerini anahtarın “doğal düzeni” ile düzenlenmiş tutmak istiyorsanız , TreeMap
veya tuşlarını kullanın ConcurrentSkipListMap
. “Doğal düzen” terimi, uygulanan anahtarların sınıfı anlamına gelir Comparable
. compareTo
Sıralamada karşılaştırma için yöntem tarafından döndürülen değer kullanılır.
Anahtarlarınızın sıralı bir sıralamanın korunmasında kullanılması için özel bir sıralama rutini belirtmek istiyorsanız, anahtarlarınızın Comparator
sınıfına uygun bir uygulama geçirin. Ya TreeMap
da ConcurrentSkipListMap
, ya geçerek kullanın Comparator
.
Haritanızın çiftlerinin, haritaya eklediğiniz orijinal sıralarında tutulmasını istiyorsanız, düğmesini kullanın LinkedHashMap
.
Anahtarlarınız gibi DayOfWeek
ya Month
da anahtarlarınız gibi bir numaralandırma kullanıyorsanız, EnumMap
sınıfı kullanın . Bu sınıf çok az bellek kullanmak ve çok hızlı çalışmak için son derece optimize edilmiş olmakla kalmaz , aynı zamanda çiftlerinizi numaralandırma tarafından tanımlanan sırayla korur. Örneğin DayOfWeek
, anahtarı DayOfWeek.MONDAY
ilk kez yinelendiğinde DayOfWeek.SUNDAY
bulunacak ve anahtarı son olacaktır.
Bir Map
uygulama seçerken aşağıdakileri de göz önünde bulundurun:
Collections::synchronizedMap
(daha az tercih edilir) ile sarın .Bu hususların her ikisi de yukarıdaki grafik tablosunda ele alınmıştır.
EnumMap
, çünkü ilk kez duydum. Muhtemelen bunun işe yarayabileceği birçok durum vardır.
Sıralama her zaman belirli harita uygulamasına bağlı olacaktır. Java 8'i kullanarak aşağıdakilerden birini kullanabilirsiniz:
map.forEach((k,v) -> { System.out.println(k + ":" + v); });
Veya:
map.entrySet().forEach((e) -> {
System.out.println(e.getKey() + " : " + e.getValue());
});
Sonuç aynı olacaktır (aynı sıralama). Aynı sırayı almak için harita tarafından desteklenen inputSet. İkincisi lambdas kullanmanıza izin verdiği için kullanışlıdır, örneğin yalnızca 5'ten büyük Integer nesnelerini yazdırmak istiyorsanız:
map.entrySet()
.stream()
.filter(e-> e.getValue() > 5)
.forEach(System.out::println);
Aşağıdaki kod, LinkedHashMap ve normal HashMap (örnek) üzerinden yinelemeyi gösterir. Sırada fark göreceksiniz:
public class HMIteration {
public static void main(String[] args) {
Map<Object, Object> linkedHashMap = new LinkedHashMap<>();
Map<Object, Object> hashMap = new HashMap<>();
for (int i=10; i>=0; i--) {
linkedHashMap.put(i, i);
hashMap.put(i, i);
}
System.out.println("LinkedHashMap (1): ");
linkedHashMap.forEach((k,v) -> { System.out.print(k + " (#="+k.hashCode() + "):" + v + ", "); });
System.out.println("\nLinkedHashMap (2): ");
linkedHashMap.entrySet().forEach((e) -> {
System.out.print(e.getKey() + " : " + e.getValue() + ", ");
});
System.out.println("\n\nHashMap (1): ");
hashMap.forEach((k,v) -> { System.out.print(k + " (#:"+k.hashCode() + "):" + v + ", "); });
System.out.println("\nHashMap (2): ");
hashMap.entrySet().forEach((e) -> {
System.out.print(e.getKey() + " : " + e.getValue() + ", ");
});
}
}
LinkedHashMap (1):
10 (# = 10): 10, 9 (# = 9): 9, 8 (# = 8): 8, 7 (# = 7): 7, 6 (# = 6): 6, 5 (# = 5 ): 5, 4 (# = 4): 4, 3 (# = 3): 3, 2 (# = 2): 2, 1 (# = 1): 1, 0 (# = 0): 0,
LinkedHashMap (2):
10: 10, 9: 9, 8: 8, 7: 7, 6: 6, 5: 5, 4: 4, 3: 3, 2: 2, 1: 1, 0: 0,
HashMap (1):
0 (#: 0): 0, 1 (#: 1): 1, 2 (#: 2): 2, 3 (#: 3): 3, 4 (#: 4): 4, 5 (#: 5 ): 5, 6 (#: 6): 6, 7 (#: 7): 7, 8 (#: 8): 8, 9 (#: 9): 9, 10 (#: 10): 10,
HashMap (2):
0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10,
Java 8 kullanın:
map.entrySet().forEach(entry -> System.out.println(entry.getValue()));
Bunu jenerikler kullanarak yapabilirsiniz:
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<Integer, Integer> entry = entries.next();
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
Bir Harita üzerinde etkili bir yinelemeli çözüm, Java 5'ten Java 7'ye bir 'her biri için' döngüsüdür.
for (String key : phnMap.keySet()) {
System.out.println("Key: " + key + " Value: " + phnMap.get(key));
}
Java 8'den bir Harita üzerinde yineleme yapmak için bir lambda ifadesi kullanabilirsiniz. Geliştirilmiş bir 'forEach'
phnMap.forEach((k,v) -> System.out.println("Key: " + k + " Value: " + v));
Eğer lambda için bir koşul yazmak istiyorsanız, bunu şöyle yazabilirsiniz:
phnMap.forEach((k,v)->{
System.out.println("Key: " + k + " Value: " + v);
if("abc".equals(k)){
System.out.println("Hello abc");
}
});
//Functional Oprations
Map<String, String> mapString = new HashMap<>();
mapString.entrySet().stream().map((entry) -> {
String mapKey = entry.getKey();
return entry;
}).forEach((entry) -> {
String mapValue = entry.getValue();
});
//Intrator
Map<String, String> mapString = new HashMap<>();
for (Iterator<Map.Entry<String, String>> it = mapString.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, String> entry = it.next();
String mapKey = entry.getKey();
String mapValue = entry.getValue();
}
//Simple for loop
Map<String, String> mapString = new HashMap<>();
for (Map.Entry<String, String> entry : mapString.entrySet()) {
String mapKey = entry.getKey();
String mapValue = entry.getValue();
}
Bunu yapmanın birçok yolu var. Aşağıda birkaç basit adım bulunmaktadır:
Bir Haritanız olduğunu varsayalım:
Map<String, Integer> m = new HashMap<String, Integer>();
Ardından, harita öğeleri üzerinde yineleme yapmak için aşağıdaki gibi bir şey yapabilirsiniz.
// ********** Using an iterator ****************
Iterator<Entry<String, Integer>> me = m.entrySet().iterator();
while(me.hasNext()){
Entry<String, Integer> pair = me.next();
System.out.println(pair.getKey() + ":" + pair.getValue());
}
// *********** Using foreach ************************
for(Entry<String, Integer> me : m.entrySet()){
System.out.println(me.getKey() + " : " + me.getValue());
}
// *********** Using keySet *****************************
for(String s : m.keySet()){
System.out.println(s + " : " + m.get(s));
}
// *********** Using keySet and iterator *****************
Iterator<String> me = m.keySet().iterator();
while(me.hasNext()){
String key = me.next();
System.out.println(key + " : " + m.get(key));
}
package com.test;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class Test {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("ram", "ayodhya");
map.put("krishan", "mathura");
map.put("shiv", "kailash");
System.out.println("********* Keys *********");
Set<String> keys = map.keySet();
for (String key : keys) {
System.out.println(key);
}
System.out.println("********* Values *********");
Collection<String> values = map.values();
for (String value : values) {
System.out.println(value);
}
System.out.println("***** Keys and Values (Using for each loop) *****");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("Key: " + entry.getKey() + "\t Value: "
+ entry.getValue());
}
System.out.println("***** Keys and Values (Using while loop) *****");
Iterator<Entry<String, String>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, String> entry = (Map.Entry<String, String>) entries
.next();
System.out.println("Key: " + entry.getKey() + "\t Value: "
+ entry.getValue());
}
System.out
.println("** Keys and Values (Using java 8 using lambdas )***");
map.forEach((k, v) -> System.out
.println("Key: " + k + "\t value: " + v));
}
}