Skip to content

Commit f47f3ee

Browse files
pawelkrupinskims-tg
authored andcommitted
Add HashMap #map, #mapKeys, #mapValues + convert to/from j.u.Map
1 parent 8f0e035 commit f47f3ee

File tree

2 files changed

+94
-7
lines changed

2 files changed

+94
-7
lines changed

core/src/main/java/fj/data/HashMap.java

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package fj.data;
22

3-
import fj.Equal;
4-
import fj.F;
5-
import fj.Hash;
6-
import fj.P2;
3+
import fj.*;
74

85
import java.util.Collection;
96
import java.util.Iterator;
@@ -69,6 +66,13 @@ public HashMap(final Equal<K> e, final Hash<K> h) {
6966
this.h = h;
7067
}
7168

69+
public HashMap(java.util.Map<K, V> map, final Equal<K> e, final Hash<K> h) {
70+
this(e, h);
71+
for (K key : map.keySet()) {
72+
set(key, map.get(key));
73+
}
74+
}
75+
7276
/**
7377
* Construct a hash map with the given equality and hashing strategy.
7478
*
@@ -82,7 +86,11 @@ public HashMap(final Equal<K> e, final Hash<K> h, final int initialCapacity) {
8286
this.h = h;
8387
}
8488

85-
/**
89+
public HashMap(java.util.Map<K, V> map) {
90+
this(map, Equal.<K>anyEqual(), Hash.<K>anyHash());
91+
}
92+
93+
/**
8694
* Construct a hash map with the given equality and hashing strategy.
8795
*
8896
* @param e The equality strategy.
@@ -243,6 +251,43 @@ public Option<V> getDelete(final K k) {
243251
return fromNull(m.remove(new Key<K>(k, e, h)));
244252
}
245253

254+
public <A, B> HashMap<A, B> map(F<K, A> keyFunction,
255+
F<V, B> valueFunction,
256+
Equal<A> equal, Hash<A> hash) {
257+
final HashMap<A, B> hashMap = new HashMap<A, B>(equal, hash);
258+
for (K key : keys()) {
259+
final A newKey = keyFunction.f(key);
260+
final B newValue = valueFunction.f(get(key).some());
261+
hashMap.set(newKey, newValue);
262+
}
263+
return hashMap;
264+
}
265+
266+
public <A, B> HashMap<A, B> map(F<K, A> keyFunction,
267+
F<V, B> valueFunction) {
268+
return map(keyFunction, valueFunction, Equal.<A>anyEqual(), Hash.<A>anyHash());
269+
}
270+
271+
public <A, B> HashMap<A, B> map(F<P2<K, V>, P2<A, B>> function, Equal<A> equal, Hash<A> hash) {
272+
return from(toStream().map(function), equal, hash);
273+
}
274+
275+
public <A, B> HashMap<A, B> map(F<P2<K, V>, P2<A, B>> function) {
276+
return from(toStream().map(function));
277+
}
278+
279+
public <A> HashMap<A, V> mapKeys(F<K, A> keyFunction, Equal<A> equal, Hash<A> hash) {
280+
return map(keyFunction, Function.<V>identity(), equal, hash);
281+
}
282+
283+
public <A> HashMap<A, V> mapKeys(F<K, A> function) {
284+
return mapKeys(function, Equal.<A>anyEqual(), Hash.<A>anyHash());
285+
}
286+
287+
public <B> HashMap<K, B> mapValues(F<V, B> function) {
288+
return map(Function.<K>identity(), function, e, h);
289+
}
290+
246291
public List<P2<K, V>> toList() {
247292
return keys().map(new F<K, P2<K, V>>() {
248293
public P2<K, V> f(final K k) {
@@ -272,6 +317,14 @@ public Array<P2<K, V>> toArray() {
272317
return toList().toArray();
273318
}
274319

320+
public java.util.Map<K, V> toMap() {
321+
final java.util.HashMap<K,V> result = new java.util.HashMap<K, V>();
322+
for (K key : keys()) {
323+
result.put(key, get(key).some());
324+
}
325+
return result;
326+
}
327+
275328
public static <K, V> HashMap<K, V> from(Iterable<P2<K, V>> entries) {
276329
return from(entries, Equal.<K>anyEqual(), Hash.<K>anyHash());
277330
}

core/src/test/fj/data/CheckHashMap.scala

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ package data
33

44
import org.scalacheck.Prop._
55
import ArbitraryHashMap._
6-
import Equal.{intEqual, stringEqual, optionEqual}
7-
import Hash.intHash
6+
import Equal._
7+
import Hash._
8+
import Ord._
89
import fj.data.Option._
910
import scala.collection.JavaConversions._
1011
import org.scalacheck.{Arbitrary, Properties}
1112
import data.ArbitraryList._
1213
import org.scalacheck.Arbitrary._
14+
import java.util.Map
1315

1416
object CheckHashMap extends Properties("HashMap") {
1517
implicit val equalInt: Equal[Int] = intEqual comap ((x: Int) => (x: java.lang.Integer))
@@ -69,4 +71,36 @@ object CheckHashMap extends Properties("HashMap") {
6971
.forall((e: (Int, Iterable[P2[Int, String]])) => e._2
7072
.exists((elem: P2[Int, String]) => optionEqual(stringEqual).eq(map.get(e._1), Option.some(elem._2))))
7173
})
74+
75+
property("map") = forAll((m: HashMap[Int, String]) => {
76+
val keyFunction: F[Int, String] = (i: Int) => i.toString
77+
val valueFunction: (String) => String = (s: String) => s + "a"
78+
val mapped = m.map(keyFunction, valueFunction, stringEqual, stringHash)
79+
val keysAreEqual = m.keys().map(keyFunction).toSet == mapped.keys.toSet
80+
val appliedFunctionsToKeysAndValues: Boolean = m.keys().forall((key: Int) => {
81+
val mappedValue = mapped.get(keyFunction.f(key))
82+
val oldValueMapped = some(valueFunction.f(m.get(key).some()))
83+
Equal.optionEqual(stringEqual).eq(mappedValue, oldValueMapped)
84+
})
85+
86+
keysAreEqual && appliedFunctionsToKeysAndValues
87+
})
88+
89+
property("toMap") = forAll((m: HashMap[Int, String]) => {
90+
val toMap: Map[Int, String] = m.toMap
91+
m.keys().forall((key: Int) => m.get(key).some() == toMap.get(key))
92+
})
93+
94+
property("fromMap") = forAll((m: HashMap[Int, String]) => {
95+
val map = new java.util.HashMap[Int, String]()
96+
m.keys().foreach((key: Int) => {
97+
map.put(key, m.get(key).some())
98+
Unit.unit()
99+
})
100+
val fromMap: HashMap[Int, String] = new HashMap[Int, String](map)
101+
val keysAreEqual = m.keys.toSet == fromMap.keys.toSet
102+
val valuesAreEqual = m.keys().forall((key: Int) =>
103+
optionEqual(stringEqual).eq(m.get(key), fromMap.get(key)))
104+
keysAreEqual && valuesAreEqual
105+
})
72106
}

0 commit comments

Comments
 (0)