Funktion verallgemeinern

Status
Nicht offen für weitere Antworten.

Bit2_Gosu

Bekanntes Mitglied
Hi!

Ich habe mir folgende recht allgemeine Funktion geschrieben:

Code:
public Map.Entry <String, String> getRandomMapEntry(
			Map <String, String> map)
	{
		Random random = new Random();
		Set <Map.Entry <String, String>> entrySet = map.entrySet();
		Iterator <Map.Entry <String, String>> it = entrySet.iterator();
		Map.Entry <String, String> mapEntry;
		int size = entrySet.size();
		int zahl = random.nextInt(size);
		for (int i = 0; i < size; i++)
		{
			mapEntry = it.next();
			if (i == zahl)
			{
				return mapEntry;
			}
		}
		return null;
	}

Nun würde ich gerne, dass die Funktion nicht nur Maps vom Typ <String, String> annimmt, sondern auch anders parametrisierte Maps.

Würdet ihr da die Parametrisierung < , > weglassen? Dann meckert aber der Compiler und ich frage mich, ob das so sauber wäre..
 
Man kann auch Methoden parametrisieren:
Code:
public <K, V> Map.Entry<K, V> getRandomMapEntry(Map<K, V> map) {
    Random random = new Random();
    Set<Map.Entry<K, V>> entrySet = map.entrySet();
    Iterator<Map.Entry<K, V>> it = entrySet.iterator();
    Map.Entry<K, V> mapEntry;
    int size = entrySet.size();
    int zahl = random.nextInt(size);
    for (int i = 0; i < size; i++) {
        mapEntry = it.next();
        if (i == zahl) {
            return mapEntry;
        }
    }
    return null;
}
 
entweder du lässt halt die generics weg, oder gibst den typ object an, wenn du damit die warnungen "abschalten" willst

trotzdem fällt dann aber noch weiter arbeit an, da du dann innerhalb der methode auf den objektyp überprüfen und casten musst.

kann ja auch sein dass es kein string oder kein int ist, was sich in der map befindet
 
Du musst in der Methode nicht casten. In der Zeit vor Generics hat man sowas halt mit Object gelöst. Casten muss man nur überall dort, wo man die Methode dann verwendet.
 
stimmt, falsch überflogen, "zahl" kommt ja garnicht aus der map 🙂 sorry

ja, aber casten bleibt ihm wohl trotzdem nicht erspart 🙂
 
Also das:

Code:
public <K, V> Map.Entry<K, V> getRandomMapEntry(Map<K, V> map) { 
    Random random = new Random(); 
    Set<Map.Entry<K, V>> entrySet = map.entrySet(); 
    Iterator<Map.Entry<K, V>> it = entrySet.iterator(); 
    Map.Entry<K, V> mapEntry; 
    int size = entrySet.size(); 
    int zahl = random.nextInt(size); 
    for (int i = 0; i < size; i++) { 
        mapEntry = it.next(); 
        if (i == zahl) { 
            return mapEntry; 
        } 
    } 
    return null; 
}

hört sich irgendwie am besten an 😉

Ich verstehe nur
<K, V> Map.Entry<K, V>
nicht..
Also die Methode returned ein Objekt vom Typ Map.Entry<K, V>. Aber wozu ist dann das <K, V> vor dem return Typ da?
 
Code:
Map<JLabel,Thread> map = new HashMap<JLabel,Thread>();
...
Map.Entry<JLabel,Thread> zufallselement = getRandomMapEntry(map);

JLabel label = zufallselement.getKey();
Thread thread = zufallselement.getValue();
Wo wird da gecastet?
Es ist doch gerade der Sinn von Generics, dass man nicht casten muss.


Ich verstehe nur
<K, V> Map.Entry<K, V>
nicht..
Also die Methode returned ein Objekt vom Typ Map.Entry<K, V>. Aber wozu ist dann das <K, V> vor dem return Typ da?
K und V sind die Parameter der Methode. Das ist ganz analog zu den Parametern einer Klasse.
Beim Aufruf muss man sie nicht mal angeben, da es der Compiler normalerweise schafft, die richtigen Typen
herauszufinden. Man kann sie aber trotzdem explizit angeben, z.B.:
Code:
this.<JLabel, Thread> getRandomMapEntry(map);
wobei der Aufruf in diesem Beispiel in der gleichen Klasse stattfindet, in der auch die Methode definiert ist (daher das this.)
 
Also diese Antwort verstehe ich leider nicht..

Wo wäre denn der logische Fehler, wenn ich das erste <K, V> weglasse?
 
Dann ist die Methode nicht parametrisiert. Das würde nicht kompiliert werden.
Parametrisieren = Verallgemeinen, und das wolltest du doch.

EDIT: In diesem Beispiel sieht es zugegeben etwas sinnlos aus, aber man kann
auch folgendes machen:
Code:
<K extends Comparable, V extends Number>
Damit würde man die Parameter mit Einschränkungen (Bounds) versehen.
 
Ah, jetzt hab ich es glaube ich verstanden!

Nicht nur der return Typ, sondern auch die Methode wird parametrisiert (wie du es ja auch schon gesagt hast)!

Vielen Dank an alle 😉
 
Sorry, aber ich habe doch noch mal eine Frage, zu <K, V>

Bei:

Code:
public Map.Entry <String, String> getRandomMapEntry( 
         Map <String, String> map) 
   { 
      Random random = new Random(); 
      Set <Map.Entry <String, String>> entrySet = map.entrySet(); 
      Iterator <Map.Entry <String, String>> it = entrySet.iterator(); 
      Map.Entry <String, String> mapEntry; 
      int size = entrySet.size(); 
      int zahl = random.nextInt(size); 
      for (int i = 0; i < size; i++) 
      { 
         mapEntry = it.next(); 
         if (i == zahl) 
         { 
            return mapEntry; 
         } 
      } 
      return null; 
   }

muss ich ja auch nicht schreiben
public <String, String> Map.Entry <String, String> ...

Warum muss ich das aber bei <K, V> ??
 
Code:
public Map.Entry <String, String> getRandomMapEntry(Map <String, String> map){..}
ist nicht parametrisiert.
Diese Funktion akzeptiert nur Map<String, String> und nichts anderes, d.h. die Typen sind fest vorgegeben und nicht frei. Deswegen hat man die Parameter <K,V> auch nicht.
 
Stellt dir K und V als Platzhalter vor.
Und am besten schaust du dir kurz Generics an, in einem Buch oder E-Book 🙂 Ist garnicht so schwer.
 
masta // thomas hat gesagt.:
Und am besten schaust du dir kurz Generics an, in einem Buch oder E-Book 🙂 Ist garnicht so schwer.
Find ich schon. Meiner Meinung sind Generics das kompliziertes Sprachfeature von Java.
 
Hm kennt einer von euch vielleicht eine Seite, auf der auf Deutsch oder auf nicht ganz so schwerem Englisch erklärt ist, was es eigentlich bedeutet, wenn eine Funktion parametrisiert ist?

Ich habe mir die ersten 3 Seiten von eurem Link durchgelesen und finde das wirklich sehr schwer, neben der Sprache besonders die Beispiele..
 
Die Closure-Entwürfe sind imo nur so komplex, gerade weil sie massiv auf Generics aufbauen. 😉 Wenn man also differenziert, würden Generics auf Platz 1 bleiben. :bae:
 
Also den Artikel fand ich besonders gut:

In meiner Methode sagt das erste <K, V> also überhaupt, was "K" und "V" überhaupt sein können. Ich könnte auch <K extends Comparable<K>, V> sagen, und hätte dann das <K, V> vom Argumenttyp der Funktion und auch das <K, V> des return Typs eingeschränkt. In meiner Funktion habe ich aber keine Bounds gesetzt und deshalb kann zB. "K" alles sein.

Habe ich das jetzt richtig verstanden?
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben