Iterables und size()

Status
Nicht offen für weitere Antworten.

Bit2_Gosu

Bekanntes Mitglied
Hi!

Ich habe mir mal die Klasse Iterable angeschaut und musste leider feststellen, dass es keine size() Methode gibt.

Jetzt frage ich mich einfach warum. Sowas wäre doch möglich, oder nicht?

Code:
public static <E> int getIterableSize(Iterable <E> iter)
{
	Iterator <E> it = iter.iterator();
	for (int i = 0; true; i++)
	{
		if (!it.hasNext())
		{
			return i;
		}
		it.next();
	}		
}
 
Ein Iterator muss nicht unbedingt wissen, wieviele Elemente er hat. Vielleicht werden die ja dynamisch von irgendwo geladen (siehe DB-ResultSet).
Du kannst zwar die Elemente in einer Schleife zählen um die Größe zu bestimmen, aber danach ist der Iterator wertlos, da abgearbeitet.
Was genau möchtest du denn erreichen?
 
es gibt auch bidirektionale iteratoren. einweg iteratoren sind ein (üblicher) spezialfall. die grundidee eines iterators ist schlicht, dass er eine geordnete sicht auf eine menge bietet. die zugrundeliegende datenstruktur ist dabei nicht von belang. für einige wäre es vielleicht möglich die größe anzubieten, für andere nur umständlich oder schlicht nicht möglich. z.b. könnte man auch ein netzwerkprotokoll als iterator anbieten und mit jedem schritt wird ein weiteres paket angefordet. wieviele kommen weiss niemand.

es hindert dich aber niemand daran, für eigene iteratoren das interface entsprechend aufzubohren, wenn du die größe liefern kannst.
 
Naja, ich wollte eine Funktion schreiben, die zufälliges Element einer LinkedList ausgibt. Beim schreiben der Funktion hab ich gemerkt: "hm nehm ich doch nicht nur LinkedList an, sondern allgemein alle Iterables". LinkedList ist ja z.B. auch eine Interable.

Meine Funktion braucht allerdings die size der Iterable, die übergeben wird. Die Klasse Iterable kennt aber keine Funktion size() und das hat mich gewundert. Ich könnte so nur Collections als Parameter annehmen (das wär dann so das Unterste in der hierachy, das size() kennt).

Des fand ich aber blöde und deshalb dacht ich mir, dann musst dus eben selber machen 😉

Übriegens, dass der Iterator der Funktion getIterableSize() innerhalb der Funktion verbraucht wird ist doch wumpe ?!
 
Bit2_Gosu hat gesagt.:
Übriegens, dass der Iterator der Funktion getIterableSize() innerhalb der Funktion verbraucht wird ist doch wumpe ?!
für jemanden, der die methode verwendet nicht. denn danach kennt er zwar die größe, aber muss sich einen neuen iterator besorgen, der evtl. schon wieder ganz andere elemente und eine andere anzahl liefert. daher relativ unbrauchbar 😉

nimm immer die abstrakteste klasse wie möglich als parameter, aber auf keinen fall zu abstrakt. in deinem fall (zufälliger zugriff) ist List eine gute wahl.
 
Bit2_Gosu hat gesagt.:
Übriegens, dass der Iterator der Funktion getIterableSize() innerhalb der Funktion verbraucht wird ist doch wumpe ?!
Tja, so funktionieren Iterables nun mal. Wenn einem das nicht gefällt muss man was anderes nehmen.
Aber du hast die Lösung schon gefunden. Nimm Collection (oder List). Du brauchst nunmal die Größe, und Iterables haben nicht unbedingt eine.
 
Code:
LinkedList <String> it = new LinkedList <String>();
it.add("a");
it.add("b");
it.add("c");
it.add("d");
int size = ContainerFunc.getIterableSize(it);
System.out.println(size);
Iterator <String> iterator = it.iterator();
System.out.println(iterator.next());

Das funktioniert bei mir wunderbar. Erst returnt die Funktion den Wert 4 (der Iterator innerhalb der Funktion ist verbraucht) und dann mach ich mir einen anderen Iterator, der z.B. dass erste Element der LinkedList ausgibt?

Und was spricht gegen eine Collection (statt einer List) ?

(übrigens wumpe heißt egal)
 
Wie? Jede List bietet eine Methode zum zufälligen auswählen eines Elementes an?

Die hab ich gar nicht gesehen?! Ich hatte mir selber folgende geschrieben, und die nimmt auch Collections an:

Code:
public static <E> E getRandomElement(Collection <E> coll)
{
	Random ran = new Random();
	int size = coll.size();
	int ranIndex = ran.nextInt(size);
	E ranElement = getElement(coll, ranIndex);
	return ranElement;
}
public static <E> E getElement(Iterable <E> iter, int pos)
{		
	Iterator <E> it = iter.iterator();	
	E e = null;
	for (int i = 0; i <= pos; i++)
	{	
		if (!it.hasNext())
		{
			return null;
		}
		e = it.next();
	}
	return e;
}
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben