Skip to content

Commit 77f8e02

Browse files
committed
Union
1 parent b600ab7 commit 77f8e02

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
1010
- `CmpEqBy`, `CmpEq`, `GTBy`, `GT`, `LTBy`, `LT`, `GTEBy`, `GTE`, `LTEBy`, and `LTE` inequality checks
1111
- `MinBy`, `MaxBy`, `Min`, and `Max` semigroups
1212
- `Product2-8` interfaces, representing general product types
13+
- `Union`, a semigroup that behaves like a lazy set union on `Iterable`s
1314

1415
### Changed
1516
- `Tuple2-8` now implement `Product2-8`
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.jnape.palatable.lambda.monoid.builtin;
2+
3+
import com.jnape.palatable.lambda.functions.Fn1;
4+
import com.jnape.palatable.lambda.monoid.Monoid;
5+
6+
import java.util.Collections;
7+
8+
import static com.jnape.palatable.lambda.functions.builtin.fn1.Distinct.distinct;
9+
import static com.jnape.palatable.lambda.monoid.builtin.Concat.concat;
10+
11+
/**
12+
* Given two {@link Iterable}s, return the union of all unique occurrences of elements between them. Note that this
13+
* operation preserves order, so the unique elements of the first {@link Iterable} are iterated before the unique
14+
* elements of the second {@link Iterable}.
15+
*
16+
* @param <A> the {@link Iterable} element type)
17+
*/
18+
public final class Union<A> implements Monoid<Iterable<A>> {
19+
20+
private static final Union INSTANCE = new Union();
21+
22+
private Union() {
23+
}
24+
25+
@Override
26+
public Iterable<A> identity() {
27+
return Collections::emptyIterator;
28+
}
29+
30+
@Override
31+
public Iterable<A> apply(Iterable<A> xs, Iterable<A> ys) {
32+
return distinct(concat(xs, ys));
33+
}
34+
35+
@SuppressWarnings("unchecked")
36+
public static <A> Union<A> union() {
37+
return INSTANCE;
38+
}
39+
40+
public static <A> Fn1<Iterable<A>, Iterable<A>> union(Iterable<A> xs) {
41+
return Union.<A>union().apply(xs);
42+
}
43+
44+
public static <A> Iterable<A> union(Iterable<A> xs, Iterable<A> ys) {
45+
return union(xs).apply(ys);
46+
}
47+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.jnape.palatable.lambda.monoid.builtin;
2+
3+
import com.jnape.palatable.lambda.functions.Fn1;
4+
import com.jnape.palatable.traitor.annotations.TestTraits;
5+
import com.jnape.palatable.traitor.runners.Traits;
6+
import org.junit.Test;
7+
import org.junit.runner.RunWith;
8+
import testsupport.traits.EmptyIterableSupport;
9+
import testsupport.traits.FiniteIteration;
10+
import testsupport.traits.ImmutableIteration;
11+
import testsupport.traits.InfiniteIterableSupport;
12+
import testsupport.traits.Laziness;
13+
14+
import static com.jnape.palatable.lambda.monoid.builtin.Union.union;
15+
import static java.util.Arrays.asList;
16+
import static java.util.Collections.emptyList;
17+
import static java.util.Collections.singletonList;
18+
import static org.junit.Assert.assertThat;
19+
import static testsupport.matchers.IterableMatcher.isEmpty;
20+
import static testsupport.matchers.IterableMatcher.iterates;
21+
22+
@RunWith(Traits.class)
23+
public class UnionTest {
24+
25+
@TestTraits({Laziness.class, InfiniteIterableSupport.class, EmptyIterableSupport.class, FiniteIteration.class, ImmutableIteration.class})
26+
public Fn1<Iterable<Integer>, Iterable<Integer>> testSubject() {
27+
return union(asList(1, 2, 3));
28+
}
29+
30+
@Test
31+
public void identity() {
32+
assertThat(union().identity(), isEmpty());
33+
}
34+
35+
@Test
36+
public void semigroup() {
37+
assertThat(union(emptyList(), emptyList()), isEmpty());
38+
assertThat(union(asList(1, 2), emptyList()), iterates(1, 2));
39+
assertThat(union(emptyList(), singletonList(3)), iterates(3));
40+
assertThat(union(asList(1, 2), singletonList(3)), iterates(1, 2, 3));
41+
assertThat(union(asList(1, 2, 2), singletonList(3)), iterates(1, 2, 3));
42+
assertThat(union(asList(1, 2), asList(1, 2, 3)), iterates(1, 2, 3));
43+
}
44+
}

0 commit comments

Comments
 (0)