Das Abrufen eines Elements aus einem Satz oder einer Sammlung mag als ungewöhnliche Anforderung erscheinen - wenn auch nicht willkürlich oder vielseitig -, ist jedoch durchaus üblich, wenn beispielsweise Statistiken für Schlüssel- oder Werteobjekte in einer Karte berechnet und min / initialisiert werden müssen. Maximalwerte . Das beliebige Element aus einem Set / einer Sammlung (von Map.keySet () oder Map.values () zurückgegeben) wird für diese Initialisierung verwendet, bevor die Min / Max-Werte jeweils aktualisiert werden Element .
Welche Möglichkeiten hat man also, wenn man mit diesem Problem konfrontiert wird und gleichzeitig versucht, Speicher und Ausführungszeit klein und Code klar zu halten?
Oft erhalten Sie das Übliche: " Set in ArrayList konvertieren und das erste Element erhalten ". Großartig! Ein weiteres Array mit Millionen von Elementen und zusätzlichen Verarbeitungszyklen zum Abrufen von Objekten aus Set, Zuweisen eines Arrays und Auffüllen :
HashMap<K,V> map;
List<K> list = new ArrayList<V>(map.keySet());
min = max = list.get(0).some_property();
for(i=list.size();i-->1;){
if( min > list.get(i).some_property() ){ ... }
...
}
Oder man kann eine Schleife mit einem Iterator verwenden, wobei ein Flag verwendet wird, um anzuzeigen, dass min / max initialisiert werden muss, und eine bedingte Anweisung, um zu überprüfen, ob dieses Flag für alle Iterationen in der Schleife gesetzt ist. Dies impliziert eine Menge bedingter Überprüfungen.
boolean flag = true;
Iterator it = map.keySet().iterator();
while( it.hasNext() ){
if( flag ){
min = max = it.next().some_property();
flag = false;
} else {
if( min > list.get(i).some_property() ){ min = list.get(i).some_property() }
...
}
}
Oder führen Sie die Initialisierung außerhalb der Schleife durch:
HashMap<K,V> map;
Iterator it = map.keySet().iterator();
K akey;
if( it.hasNext() ){
akey = it.next();
min = max = akey.value();
do {
if( min > list.get(i).some_property() ){ min = akey.some_property() }
} while( it.hasNext() && ((akey=it.next())!=null) );
}
Aber ist es das ganze Manöver im Namen des Programmierers (und des Einrichtens des Iterators im Auftrag der JVM) wirklich wert, wann immer Min / Max benötigt werden?
Der Vorschlag eines javally-korrekten alten Sports könnte lauten: "Wickeln Sie Ihre Karte in eine Klasse ein, die die Min- und Max-Werte beim Setzen oder Löschen verfolgt!"
Es gibt eine andere Situation , in der meiner Erfahrung nach nur ein beliebiger Gegenstand aus einer Karte benötigt wird. In diesem Fall enthält die Karte Objekte, die eine gemeinsame Eigenschaft haben - für alle in dieser Karte gleich - und Sie müssen diese Eigenschaft lesen . Angenommen, es gibt eine Karte mit Aufbewahrungsfächern desselben Histogramms mit derselben Anzahl von Dimensionen. Bei einer solchen Karte müssen Sie möglicherweise die Anzahl der Dimensionen eines beliebigen Histobins in der Karte kennen, um beispielsweise einen weiteren Histobin mit denselben Dimensionen erstellen zu können. Muss ich einen Iterator erneut einrichten und entsorgen, nachdem ich next () nur einmal aufgerufen habe? Ich werde den Vorschlag der javally-korrekten Person zu dieser Situation überspringen.
Und wenn all die Mühe , die in immer jedes Element verursacht unbedeutend Speicher und CPU - Zyklen zu erhöhen, was ist dann mit all dem Code zu schreiben hat gerade das schwer zu bekommen zu bekommen jedes Element.
Wir brauchen das beliebige Element. Gib es uns!
iterator().next()
. (Deshalb haben wir keinegetFirst(Iterable<E>)
, nur einegetFirst(Iterable<E>, E default)
.)