{"id":2622,"date":"2014-01-06T18:23:08","date_gmt":"2014-01-06T16:23:08","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=2622"},"modified":"2014-01-07T05:13:50","modified_gmt":"2014-01-07T03:13:50","slug":"map-operationen-in-abhngigkeit-von-nicht-existierenden-werten-in-java-8","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2014\/01\/map-operationen-in-abhngigkeit-von-nicht-existierenden-werten-in-java-8\/","title":{"rendered":"Map-Operationen in Abh&auml;ngigkeit von (nicht-)existierenden Werten in Java 8"},"content":{"rendered":"<p>Die Map-API hat seit Java 8 einige clevere Methoden, die mehrere Operationen zusammenfassen, wobei die Funktionsweise folgendem Bauplan entspricht: ist ein assoziierter Wert zu einem Schl\u00fcssel (nicht) vorhanden, dann tue dies, sonst das. <\/p>\n<p>interface java.util.Map&lt;K,V&gt; <\/p>\n<p>\u00a7 default V putIfAbsent(K key, V value)<br \/>Testet zuerst, ob es zu dem gegeben Schl\u00fcssel key einen assoziierten Wert existiert und wenn ja, gibt es keine \u00c4nderung an der Datenstruktur, nur der alte assoziierte Wert wird zur\u00fcckgegeben. Existiert kein assoziierter Wert, speichert die Datenstruktur zum Schl\u00fcssel den value. Die R\u00fcckgabe von putIfAbsent(\u2026) ist null, falls es vorher keinen alten assoziierten Wert gab, andernfalls die Referenz vom alten Objekt (was auch null ein kann, wenn die Map auch null-Werte erlaubt), was jetzt durch den neuen Wert \u00fcberschreiben wurde. Falls null als Wert in der Map erlaubt ist \u2013 wie etwa in HashMap \u2013 so gilt eine Besonderheit: ist ein existierender Schl\u00fcssel mit null assoziiert, dann w\u00fcrde putIfAbsent(\u2026) den Wert null mit etwas anderem \u00fcberschreiben. <\/p>\n<p>\u00a7 default V computeIfAbsent(K key, Function&lt;? super K, ? extends V&gt; mappingFunction)<br \/>Vergleichbar mit putIfAbsent(\u2026), nur nutzt diese Methode eine Berechnungsmethode statt einen festen Wert. Ein wichtiger Punkt ist, dass wenn die Berechnungsfunktion null zur\u00fcckgibt, nichts an dem Assoziativspeicher ver\u00e4ndert wird und der alte Wert bleibt. Der R\u00fcckgabewert ist immer entweder der letzte assoziierter Wert oder der neue Eintrag, es sein denn, die mappingFunction lieferte null. Die Methode l\u00e4sst sich damit perfekt in einer Methodenkaskadierung verwenden der Art map.computeIfAbsent(\u2026).methodeVonV(\u2026). <\/p>\n<p>\u00a7 default V computeIfPresent(K key, BiFunction&lt;? super K, ? super V,? extends V&gt; remappingFunction)<br \/>\u00dcberschreibt den assoziierten Wert mit einem von der Funktion berechneten neuen Wert, wenn das Schl\u00fcssel\/Werte-Paar existiert. Dann liefert die Methode denen neuen Wert zur\u00fcck. Zwei Sonderf\u00e4lle sind zu unterscheiden. Falls es zu dem Schl\u00fcssel key keinen Wert gibt macht computeIfPresent(\u2026) nichts und die R\u00fcckgabe ist null. Gibt es einen assoziierten Wert, doch die auf den Wert angewendete Funktion liefert null, wird das Schl\u00fcssel\/Werte-Paar gel\u00f6scht und die R\u00fcckgabe ist ebenfalls null. <\/p>\n<p>Beispiel. Java bietet von Haus aus keine Datenstruktur, die wie ein Assoziativspeicher arbeitetet, aber einen Schl\u00fcssel mit einer Sammlung von Werten assoziieren kann. Doch so eine Klasse ist schnell geschrieben: <\/p>\n<p>class Multimap&lt;K, V&gt; { <\/p>\n<\/p>\n<p>private final Map&lt;K, Collection&lt;V&gt;&gt; map = new HashMap&lt;&gt;(); <\/p>\n<\/p>\n<p>public Collection&lt;V&gt; get( K key ) { <\/p>\n<p>return map.getOrDefault( key, Collections.&lt;V&gt; emptyList() ); <\/p>\n<p>} <\/p>\n<\/p>\n<p>public void put( K key, V value ) { <\/p>\n<p>map.computeIfAbsent( key, k -&gt; new ArrayList&lt;&gt;() ) <\/p>\n<p>.add( value ); <\/p>\n<p>} <\/p>\n<p>} <\/p>\n<p>Ein kleines Beispiel: <\/p>\n<p>Multimap&lt;Integer, String&gt; mm = new Multimap&lt;&gt;(); <\/p>\n<p>System.out.println( mm.get( 1 ) ); \/\/ [] <\/p>\n<p>mm.put( 1, &#8222;eins&#8220; ); <\/p>\n<p>System.out.println( mm.get( 1 ) ); \/\/ [eins] <\/p>\n<p>mm.put( 1, &#8222;one&#8220; ); <\/p>\n<p>System.out.println( mm.get( 1 ) ); \/\/ [eins, one] <\/p>\n<p>interface java.util.Map&lt;K,V&gt; <\/p>\n<p>\u00a7 default V merge(K key, V value, BiFunction&lt;? super V, ? super V,? extends V&gt; remappingFunction)<br \/>Setzt einen neuen Eintrag in die Map oder verschmilzt einen existierenden Eintrag mit der angegebenen Funktion. Von der Semantik her ist das die komplexeste Methode. Der erste Fall einfach, denn wenn es zum Schl\u00fcssel kein Wert gibt; dann wird das Schl\u00fcssel-\/Werte Paar in die Map gesetzt und merge(\u2026) liefert als R\u00fcckgabe den value. Gibt es schon einen assoziierten Wert, wird die Funktion mit dem alten Wert und value auf aufgerufen (eine BiFunction hat zwei Parameter) und der alte assoziierte Wert mit diesem neuen Wert \u00fcberschrieben und die R\u00fcckgabe von merge(\u2026) liefert diesen neuen Wert. Jetzt gibt es noch zwei Sonderf\u00e4lle, und die h\u00e4ngen damit zusammen wenn das Argument value gleich null oder die Funktion null liefert. In beiden F\u00e4llen wird das Schl\u00fcssel\/Wert-Paar gel\u00f6scht und die R\u00fcckgabe von merge(\u2026) ist null. <\/p>\n<p>Beispiel: Zu einer ID soll ein Punkt assoziiert werden. Neue hinzugef\u00fcgte Punkte zu dieser ID sollen die Koordinate des urspr\u00fcnglichen Punktes verschieben. <\/p>\n<p>Map&lt;Integer, Point&gt; map = new HashMap&lt;&gt;(); <\/p>\n<p>BiFunction&lt;? super Point, ? super Point, ? extends Point&gt; remappingFunc = <\/p>\n<p>(oldVal, val) -&gt; { val.translate( oldVal.x, oldVal.y ); return val; }; <\/p>\n<p>map.merge( 1, new Point( 12, 3 ), remappingFunc ); <\/p>\n<p>System.out.println( map.get( 1 ) ); \/\/ java.awt.Point[x=12,y=3]  <\/p>\n<p>map.merge( 1, new Point( -2, 2 ), remappingFunc ); <\/p>\n<p>System.out.println( map.get( 1 ) ); \/\/ java.awt.Point[x=10,y=5] <\/p>\n<p>map.merge( 1, new Point( 0, 5 ), remappingFunct ); <\/p>\n<p>System.out.println( map.get( 1 ) ); \/\/ java.awt.Point[x=10,y=10]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Die Map-API hat seit Java 8 einige clevere Methoden, die mehrere Operationen zusammenfassen, wobei die Funktionsweise folgendem Bauplan entspricht: ist ein assoziierter Wert zu einem Schl\u00fcssel (nicht) vorhanden, dann tue dies, sonst das. interface java.util.Map&lt;K,V&gt; \u00a7 default V putIfAbsent(K key, V value)Testet zuerst, ob es zu dem gegeben Schl\u00fcssel key einen assoziierten Wert existiert und [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","_links_to":"","_links_to_target":""},"categories":[11,66],"tags":[],"class_list":["post-2622","post","type-post","status-publish","format-standard","hentry","category-insel","category-java-8"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/2622","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/comments?post=2622"}],"version-history":[{"count":2,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/2622\/revisions"}],"predecessor-version":[{"id":2624,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/2622\/revisions\/2624"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=2622"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=2622"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=2622"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}