net.ranides.assira.collection.map
Class MapBiAdapter<K,VS,VT>

java.lang.Object
  extended by net.ranides.assira.collection.map.MapAdapter<K,VS,VT>
      extended by net.ranides.assira.collection.map.MapBiAdapter<K,VS,VT>
Type Parameters:
K -
VS -
VT -
All Implemented Interfaces:
Map<K,VT>, CoFunction<Map.Entry<K,VT>,VS>, Function<VT,Map.Entry<K,VS>>
Direct Known Subclasses:
MapBiAdapterTT

public abstract class MapBiAdapter<K,VS,VT>
extends MapAdapter<K,VS,VT>
implements CoFunction<Map.Entry<K,VT>,VS>

Klasa abstrakcyjna umożliwiająca leniwą konwersję listy elementów między dwoma formatami w obie strony (a więc tworzenie map do odczytu i zapisu). Konwertowane są tylko wartości umieszczone w mapie - klucze nie mogą być transformowane.

Ogólny wariant adaptera zakłada, że konwersja może zwracać jako wynik obiekty innej klasy, niż źródłowa. Specjalizacja MapBiAdapterTT służy do przeprowadzania konwersji, które mają wpływ jedynie na wartości, ale nie na klasy elementów.

Rozwiązuje problem synchronizacji między dwoma mapami, które reprezentują ten sam zbiór, ale w innym formacie: modyfikacja jednej natychmiast aktualizuje drugą - nie musimy pamiętać o kontroli spójności oraz wstawianiu do obu map wartości w odpowiednich formatach. Scenariusze w których MapAdapter dobrze się sprawdza:

      // spójna obsługa dwóch map
      Map<K,INTERN> source = ...
      Map<K,PUBLIC> target = konwersja
      ...
      operacje get(PUBLIC & INTERN) + put(PUBLIC & INTERN)

      // mieszana obsługa dwóch map
      Map<K,INTERN> source = ...
      Map<K,PUBLIC> target = konwersja
      ...
      bardzo dużo operacji na get(PUBLIC) + put(PUBLIC & INTERN)

      // obsługa dwóch map niszcząca aktualność danych (A)
      Map<K,INTERN> source = ...
      Map<K,PUBLIC> target = konwersja
      ...
      bardzo dużo operacji na get(PUBLIC & INTERN) + put(PUBLIC)

      // obsługa dwóch map niszcząca aktualność danych (B)
      Map<K,INTERN> source = ...
      Map<K,PUBLIC> target = konwersja
      ...
      bardzo dużo operacji na get(PUBLIC & INTERN) + put(INTERN)

      // obsługa dwóch list niszcząca spójność danych (C)
      Map<K,INTERN> source = ...
      Map<K,PUBLIC> target = konwersja
      ...
      bardzo dużo operacji na get(PUBLIC & INTERN) + put(INTERN) + put(PUBLIC)
 

Wada: konwersja odbywa się przy każdym odczycie i zapisie, jeśli mapa adaptująca jest bardzo intensywnie używana klasyczne rozwiązanie będzie znacznie wydajniejsze (jakkolwiek mapa źródłowa nie będzie na bieżąco odświeżana):

      Map<K,INTERN> source = ...
      Map<K,PUBLIC> target = konwersja
      ...
      bardzo dużo operacji get(PUBLIC) + put(PUBLIC)
      ...
      source = konwersja powrotna
 

"bardzo intensywne użycie" jest pojęciem bardzo względnym. W przypadku adapterów list można oszacować ilość operacji odczytu/zapisu, która jest granicą użyteczności adaptera. W przypadku map takie oszacowanie jest praktycznie niemożliwe, a granica dużo dalej przesunięta, ponieważ dzięki adapterowi unikamy kosztu przeindeksowania kluczy. Koszt przebudowania całej mapy może być ekstremalnie wysoki, zarówno dla TreeMap (przebudowa drzewa) jak i HashMap (przechashowanie wszystkich kluczy). Również narzut pamięciowy związany z konstrukcją map jest ekstremalnie wyższy od konstrukcji np ArrayList.

Zasadniczo utworzenie adaptera zamiast przebudowy całej istniejącej mapy na nowy format powinno być preferowane.
Rezygnacja z adapterów powinna być poparta wynikami realnych testów wydajnościowych. nie wykażą inaczej.
W metodach apply oraz inverse można nie tylko konwertować wartości, ale również logować operacje odczytu i zapisu.
Z tego powodu adapter może być użyty z powodzeniem jako wydajna realizacja obserwatora.

Author:
ranides

Nested Class Summary
 
Nested classes/interfaces inherited from interface java.util.Map
Map.Entry<K,V>
 
Constructor Summary
MapBiAdapter(Map<K,VS> content)
          Tworzy nowy adapter odwzorowujący podaną mapę.
 
Method Summary
 VT put(K key, VT value)
           
 
Methods inherited from class net.ranides.assira.collection.map.MapAdapter
clear, containsKey, containsValue, entrySet, get, isEmpty, keySet, putAll, remove, size, toString, values
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface net.ranides.assira.generic.CoFunction
inverse
 
Methods inherited from interface java.util.Map
equals, hashCode
 
Methods inherited from interface net.ranides.assira.generic.Function
apply
 

Constructor Detail

MapBiAdapter

public MapBiAdapter(Map<K,VS> content)
Tworzy nowy adapter odwzorowujący podaną mapę.

Parameters:
content -
Method Detail

put

public VT put(K key,
              VT value)
Specified by:
put in interface Map<K,VT>
Overrides:
put in class MapAdapter<K,VS,VT>


Copyright © 2013. All Rights Reserved.