Skip to content

Commit c7f1c41

Browse files
committed
functionaljava#175: Added Set toStream and TreeMap toList and toStream
1 parent 2ac9d52 commit c7f1c41

6 files changed

Lines changed: 69 additions & 10 deletions

File tree

core/src/main/java/fj/Ord.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,14 @@ public static <A, B> Ord<P2<A, B>> p2Ord(final Ord<A> oa, final Ord<B> ob) {
458458
return ord(curry((P2<A, B> a, P2<A, B> b) -> oa.eq(a._1(), b._1()) ? ob.compare(a._2(), b._2()) : oa.compare(a._1(), b._1())));
459459
}
460460

461+
public static <A, B> Ord<P2<A, B>> p2Ord1(Ord<A> oa) {
462+
return ord(p1 -> p2 -> oa.compare(p1._1(), p2._1()));
463+
}
464+
465+
public static <A, B> Ord<P2<A, B>> p2Ord2(Ord<B> ob) {
466+
return ord(p1 -> p2 -> ob.compare(p1._2(), p2._2()));
467+
}
468+
461469
/**
462470
* An order instance for a product-3, with the first factor considered most significant.
463471
*

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,17 @@ public final List<A> toList() {
283283
*
284284
* @return a stream representation of this set.
285285
*/
286-
public final Stream<A> toStream() {
287-
return foldMap(Stream.<A>single(), Monoid.<A>streamMonoid());
288-
}
286+
public final Stream<A> toStream() {
287+
if (isEmpty()) {
288+
return Stream.nil();
289+
} else if (l().isEmpty()) {
290+
return Stream.cons(head(), () -> r().toStream());
291+
} else {
292+
return l().toStream().append(Stream.cons(head(), () -> r().toStream()));
293+
}
294+
}
289295

290-
/**
296+
/**
291297
* Binds the given function across this set.
292298
*
293299
* @param o An order for the elements of the target set.

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,14 @@ public Map<K, V> toMutableMap() {
182182
return m;
183183
}
184184

185-
public Stream<P2<K, V>> toStream() {
186-
return Stream.iteratorStream(iterator());
187-
}
185+
public Stream<P2<K, V>> toStream() {
186+
return tree.toStream().map(p -> p.map2(o -> o.some()));
187+
}
188+
189+
public List<P2<K, V>> toList() {
190+
return tree.toList().map(p -> p.map2(o -> o.some()));
191+
}
192+
188193
/**
189194
* An immutable projection of the given mutable map.
190195
*

props-core/src/test/java/fj/data/properties/SetProperties.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22

33
import fj.Equal;
44
import fj.Ord;
5+
import fj.data.List;
56
import fj.data.Set;
7+
import fj.data.Stream;
68
import fj.test.Arbitrary;
79
import fj.test.Property;
810
import fj.test.reflect.CheckParams;
911
import fj.test.runner.PropertyTestRunner;
1012
import org.junit.runner.RunWith;
1113

14+
import static fj.test.Property.prop;
1215
import static fj.test.Property.property;
1316

1417
/**
@@ -18,9 +21,19 @@
1821
@CheckParams(maxSize = 10000)
1922
public class SetProperties {
2023

24+
public final static Arbitrary<Set<Integer>> as = Arbitrary.arbSet(Ord.intOrd, Arbitrary.arbInteger, 5);
25+
2126
Property setToListIsSorted() {
22-
Arbitrary<Set<Integer>> as = Arbitrary.arbSet(Ord.intOrd, Arbitrary.arbInteger);
23-
return property(as, s -> Property.prop(s.toList().equals(s.toList().sort(Ord.intOrd))));
27+
return property(as, s -> prop(s.toList().equals(s.toList().sort(Ord.intOrd))));
2428
}
2529

30+
Property stream() {
31+
return property(as, s -> {
32+
Equal<List<Integer>> eq = Equal.listEqual(Equal.intEqual);
33+
List<Integer> l1 = s.toList();
34+
List<Integer> l2 = s.toStream().toList();
35+
return prop(eq.eq(l1, l2));
36+
});
37+
}
38+
2639
}

props-core/src/test/java/fj/data/properties/TreeMapProperties.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package fj.data.properties;
22

33
import fj.Equal;
4+
import fj.Ord;
5+
import fj.P2;
6+
import fj.data.List;
7+
import fj.data.Stream;
48
import fj.data.TreeMap;
59
import fj.test.Arbitrary;
610
import fj.test.Gen;
@@ -11,6 +15,8 @@
1115

1216
import java.util.concurrent.atomic.AtomicInteger;
1317

18+
import static fj.Equal.intEqual;
19+
import static fj.Equal.p2Equal;
1420
import static fj.Equal.stringEqual;
1521
import static fj.Ord.intOrd;
1622
import static fj.test.Arbitrary.arbInteger;
@@ -29,6 +35,9 @@ public class TreeMapProperties {
2935
private static final int midMax = 20;
3036
public static final Arbitrary<TreeMap<Integer, String>> smallArbTreeMapIS = arbTreeMap(intOrd, arbInteger, arbString, smallMax);
3137
public static final Arbitrary<TreeMap<Integer, String>> arbTreeMapIS = arbTreeMap(intOrd, arbInteger, arbString, midMax);
38+
public static final Ord<P2<Integer, String>> p2Ord = Ord.p2Ord1(Ord.intOrd);
39+
Equal<List<P2<Integer, String>>> listEq = Equal.listEqual(p2Equal(intEqual, stringEqual));
40+
3241

3342
public Property empty() {
3443
return property(smallArbTreeMapIS, tm -> impliesBoolean(tm.isEmpty(), tm.size() == 0));
@@ -66,4 +75,16 @@ public Property maxKey() {
6675
);
6776
}
6877

78+
Property listSize() {
79+
return property(arbTreeMapIS, tm -> prop(tm.size() == tm.toList().length()));
80+
}
81+
82+
Property listSorted() {
83+
return property(arbTreeMapIS, tm -> prop(listEq.eq(tm.toList(), tm.toList().sort(p2Ord))));
84+
}
85+
86+
Property listStreamEq() {
87+
return property(arbTreeMapIS, tm -> prop(listEq.eq(tm.toList(), tm.toStream().toList())));
88+
}
89+
6990
}

quickcheck/src/main/java/fj/test/Arbitrary.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,13 @@ public static <A> Arbitrary<Set<A>> arbSet(Ord<A> ord, final Arbitrary<A> aa) {
818818
return arbitrary(arbList(aa).gen.map(list -> Set.set(ord, list)));
819819
}
820820

821-
/**
821+
public static <A> Arbitrary<Set<A>> arbSet(Ord<A> ord, final Arbitrary<A> aa, int max) {
822+
Gen<Set<A>> g = Gen.choose(0, max).bind(i -> Gen.sequenceN(i, aa.gen)).map(list -> Set.set(ord, list));
823+
return arbitrary(g);
824+
}
825+
826+
827+
/**
822828
* Returns an arbitrary implementation for throwables.
823829
*
824830
* @param as An arbitrary used for the throwable message.

0 commit comments

Comments
 (0)