11package com .jnape .palatable .lambda .lens .lenses ;
22
3+ import com .jnape .palatable .lambda .functions .builtin .fn2 .Filter ;
34import com .jnape .palatable .lambda .lens .Lens ;
45
56import java .util .Collection ;
89import java .util .Map ;
910import java .util .Optional ;
1011import java .util .Set ;
12+ import java .util .function .Function ;
1113
14+ import static com .jnape .palatable .lambda .functions .builtin .fn2 .Eq .eq ;
15+ import static com .jnape .palatable .lambda .functions .builtin .fn2 .Map .map ;
16+ import static com .jnape .palatable .lambda .functions .builtin .fn2 .ToCollection .toCollection ;
1217import static com .jnape .palatable .lambda .lens .Lens .lens ;
1318import static com .jnape .palatable .lambda .lens .Lens .simpleLens ;
1419import static com .jnape .palatable .lambda .lens .functions .View .view ;
1520import static com .jnape .palatable .lambda .lens .lenses .OptionalLens .unLiftA ;
21+ import static java .util .stream .Collectors .toMap ;
1622import static java .util .stream .Collectors .toSet ;
1723
1824/**
@@ -24,8 +30,7 @@ private MapLens() {
2430 }
2531
2632 /**
27- * Convenience static factory method for creating a lens that focuses on a copy of a Map. Useful for composition to
28- * avoid mutating a map reference.
33+ * A lens that focuses on a copy of a Map. Useful for composition to avoid mutating a map reference.
2934 *
3035 * @param <K> the key type
3136 * @param <V> the value type
@@ -36,8 +41,7 @@ public static <K, V> Lens.Simple<Map<K, V>, Map<K, V>> asCopy() {
3641 }
3742
3843 /**
39- * Convenience static factory method for creating a lens that focuses on a value at a key in a map, as an {@link
40- * Optional}.
44+ * A lens that focuses on a value at a key in a map, as an {@link Optional}.
4145 *
4246 * @param k the key to focus on
4347 * @param <K> the key type
@@ -52,8 +56,7 @@ public static <K, V> Lens<Map<K, V>, Map<K, V>, Optional<V>, V> valueAt(K k) {
5256 }
5357
5458 /**
55- * Convenience static factory method for creating a lens that focuses on a value at a key in a map, falling back to
56- * <code>defaultV</code> if the value is missing.
59+ * A lens that focuses on a value at a key in a map, falling back to <code>defaultV</code> if the value is missing.
5760 *
5861 * @param k the key to focus on
5962 * @param defaultValue the default value to use in case of a missing value at key
@@ -67,7 +70,7 @@ public static <K, V> Lens.Simple<Map<K, V>, V> valueAt(K k, V defaultValue) {
6770 }
6871
6972 /**
70- * Convenience static factory method for creating a lens that focuses on the keys of a map.
73+ * A lens that focuses on the keys of a map.
7174 *
7275 * @param <K> the key type
7376 * @param <V> the value type
@@ -84,8 +87,8 @@ public static <K, V> Lens.Simple<Map<K, V>, Set<K>> keys() {
8487 }
8588
8689 /**
87- * Convenience static factory method for creating a lens that focuses on the values of a map. In the case of
88- * updating the map, only the entries with a value listed in the update collection of values are kept.
90+ * A lens that focuses on the values of a map. In the case of updating the map, only the entries with a value listed
91+ * in the update collection of values are kept.
8992 *
9093 * @param <K> the key type
9194 * @param <V> the value type
@@ -104,8 +107,8 @@ public static <K, V> Lens.Simple<Map<K, V>, Collection<V>> values() {
104107 }
105108
106109 /**
107- * Convenience static factory method for creating a lens that focuses on the inverse of a map (keys and values
108- * swapped). In the case of multiple equal values becoming keys, the last one wins.
110+ * A lens that focuses on the inverse of a map (keys and values swapped). In the case of multiple equal values
111+ * becoming keys, the last one wins.
109112 *
110113 * @param <K> the key type
111114 * @param <V> the value type
@@ -122,4 +125,27 @@ public static <K, V> Lens.Simple<Map<K, V>, Map<V, K>> inverted() {
122125 return m ;
123126 });
124127 }
128+
129+ /**
130+ * A lens that focuses on a map while mapping its values with the mapping function.
131+ *
132+ * @param fn the mapping function
133+ * @param <K> the key type
134+ * @param <V> the unfocused map value type
135+ * @param <V2> the focused map value type
136+ * @return a lens that focuses on a map while mapping its values
137+ */
138+ public static <K , V , V2 > Lens .Simple <Map <K , V >, Map <K , V2 >> mappingValues (Function <? super V , ? extends V2 > fn ) {
139+ return Lens .simpleLens (m -> m .entrySet ().stream ().collect (toMap (Map .Entry ::getKey , kv -> fn .apply (kv .getValue ()))),
140+ (s , b ) -> {
141+ //todo: remove this madness upon arrival of either invertible functions or Iso<V,V2>
142+ Set <K > retainKeys = Filter .<Map .Entry <K , V >>filter (kv -> eq (fn .apply (kv .getValue ()), b .get (kv .getKey ())))
143+ .andThen (map (Map .Entry ::getKey ))
144+ .andThen (toCollection (HashSet ::new ))
145+ .apply (s .entrySet ());
146+ Map <K , V > copy = new HashMap <>(s );
147+ copy .keySet ().retainAll (retainKeys );
148+ return copy ;
149+ });
150+ }
125151}
0 commit comments