diff --git a/README.md b/README.md index eeed8ae..efb5eb9 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ safeguarding against a `StackOverflowError`. Cons List, due to its simplicity and immutability, is an ideal data structure for multi-threaded processing of ordered collections of data. -Direct implementations however, suffer from heavy recsive calls +Direct implementations however, suffer from heavy recursive calls and may cause high stack memory consumption, if not more severe issues. This implementation fuses the power of the immutable cons list with the wide range of functionality offered by the Java Collections @@ -113,7 +113,7 @@ ConsList fruit = Arrays.stream(new String[] {"Apples", "Bananas", "Orang Being an immutable collection, `ConsList` lets one save resources on defensive copying where it would otherwise have been necessary for mutable collections, -such as `ArrayList`. +such as `ArrayList`. See [ConsListBenchmark.java](cons-list-jmh/src/main/java/io/github/nblxa/ConsListBenchmark.java). @@ -121,9 +121,9 @@ Specific problems like flattening a tree-like hierarchical structure can be solved more optimally with `ConsList`, however the trivial list-growth and iteration operations perform better using `java.util.ArrayList`. -Specialized implementations for primitive types, like the `IntConsList`, +Specialized implementations for primitive types, like the `IntConsList`, for instance, may outperform `ArrayList` in some benchmarks due -to the lack of boxing. +to the lack of boxing. Here are the benchmark results on the author's machine: diff --git a/cons-list/src/main/java/io/github/nblxa/cons/ConsList.java b/cons-list/src/main/java/io/github/nblxa/cons/ConsList.java index a17460a..e914d50 100644 --- a/cons-list/src/main/java/io/github/nblxa/cons/ConsList.java +++ b/cons-list/src/main/java/io/github/nblxa/cons/ConsList.java @@ -6,6 +6,7 @@ import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; import java.util.*; +import java.util.function.Function; import java.util.stream.Collector; import java.util.stream.Collectors; @@ -221,7 +222,7 @@ static ConsList consList(@NonNull Iterable iterable) { @NonNull @SafeVarargs static ConsList concat(@NonNull ConsList first, @NonNull ConsList... rest) { - Objects.requireNonNull(first, "Null concat argument at position 0"); + Objects.requireNonNull(first, ConsUtil.MSG_NULL_CONCAT_ARG_AT_POS_0); Objects.requireNonNull(rest, ConsUtil.MSG_ARG_ARRAY_REST_IS_NULL); if (rest.length == 0) { return first; @@ -616,7 +617,7 @@ static DoubleConsList doubleConsList(@NonNull Iterable iterable) @NonNull @SafeVarargs static DoubleConsList concat(@NonNull DoubleConsList first, @NonNull DoubleConsList... rest) { - Objects.requireNonNull(first, "Null concat argument at position 0"); + Objects.requireNonNull(first, ConsUtil.MSG_NULL_CONCAT_ARG_AT_POS_0); Objects.requireNonNull(rest, ConsUtil.MSG_ARG_ARRAY_REST_IS_NULL); if (rest.length == 0) { return first; @@ -669,4 +670,17 @@ static DoubleConsList concat(@NonNull DoubleConsList first, @Non */ @NonNull ConsList reverse(); + + /** + * Eager implementation of the map method that applies mapper + * to all elements of the ConsList. + * + * The resulting new list has the same order of elements. + * + * @param mapper the mapping function to be applied to all elements + * @param new list&s element type + * @return new resulting list + */ + @NonNull + ConsList map(@NonNull Function mapper); } diff --git a/cons-list/src/main/java/io/github/nblxa/cons/ConsListImpl.java b/cons-list/src/main/java/io/github/nblxa/cons/ConsListImpl.java index 242ce5b..003d3ca 100644 --- a/cons-list/src/main/java/io/github/nblxa/cons/ConsListImpl.java +++ b/cons-list/src/main/java/io/github/nblxa/cons/ConsListImpl.java @@ -9,6 +9,7 @@ import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.*; +import java.util.function.Function; @Immutable @ThreadSafe @@ -46,6 +47,12 @@ public ConsList reverse() { return result; } + @NonNull + @Override + public ConsList map(@NonNull Function mapper) { + return ConsUtil.map(this, mapper); + } + @Override public boolean isEmpty() { return false; diff --git a/cons-list/src/main/java/io/github/nblxa/cons/ConsUtil.java b/cons-list/src/main/java/io/github/nblxa/cons/ConsUtil.java index ac5825c..e12bb72 100644 --- a/cons-list/src/main/java/io/github/nblxa/cons/ConsUtil.java +++ b/cons-list/src/main/java/io/github/nblxa/cons/ConsUtil.java @@ -1,7 +1,10 @@ package io.github.nblxa.cons; +import edu.umd.cs.findbugs.annotations.NonNull; + import java.util.Objects; import java.util.Spliterator; +import java.util.function.Function; final class ConsUtil { private ConsUtil() { @@ -60,4 +63,14 @@ static boolean haveEqualElements(DoubleConsList first, DoubleConsList< } return first == Nil.INSTANCE && second == Nil.INSTANCE; } + + @NonNull + static ConsList map(@NonNull ConsList cons, @NonNull Function mappingFunction) { + ConsList result = ConsList.nil(); + while (cons != Nil.INSTANCE) { + result = new ConsListImpl<>(mappingFunction.apply(cons.head()), result); + cons = cons.tail(); + } + return result.reverse(); + } } diff --git a/cons-list/src/main/java/io/github/nblxa/cons/DoubleConsList.java b/cons-list/src/main/java/io/github/nblxa/cons/DoubleConsList.java index df881bc..d5985a6 100644 --- a/cons-list/src/main/java/io/github/nblxa/cons/DoubleConsList.java +++ b/cons-list/src/main/java/io/github/nblxa/cons/DoubleConsList.java @@ -7,6 +7,7 @@ import java.util.NoSuchElementException; import java.util.PrimitiveIterator; import java.util.Spliterator; +import java.util.function.DoubleUnaryOperator; import java.util.stream.DoubleStream; @Immutable @@ -63,4 +64,16 @@ public interface DoubleConsList extends ConsList { */ @NonNull DoubleStream doubleStream(); + + /** + * Eager implementation of the map method that applies mapper + * to all elements of the DoubleConsList. + * + * The resulting new list has the same order of elements. + * + * @param mapper the mapping function to be applied to all elements + * @return new resulting list + */ + @NonNull + DoubleConsList doubleMap(@NonNull DoubleUnaryOperator mapper); } diff --git a/cons-list/src/main/java/io/github/nblxa/cons/DoubleConsListImpl.java b/cons-list/src/main/java/io/github/nblxa/cons/DoubleConsListImpl.java index cfea251..99b126a 100644 --- a/cons-list/src/main/java/io/github/nblxa/cons/DoubleConsListImpl.java +++ b/cons-list/src/main/java/io/github/nblxa/cons/DoubleConsListImpl.java @@ -9,6 +9,8 @@ import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.*; +import java.util.function.DoubleUnaryOperator; +import java.util.function.Function; import java.util.stream.DoubleStream; import java.util.stream.StreamSupport; @@ -49,6 +51,18 @@ public DoubleConsList doubleReverse() { return result; } + @NonNull + @Override + public DoubleConsList doubleMap(@NonNull DoubleUnaryOperator mapper) { + DoubleConsList result = ConsList.nil(); + DoubleConsList cons = this; + while (cons != Nil.INSTANCE) { + result = new DoubleConsListImpl(mapper.applyAsDouble(cons.doubleHead()), result); + cons = cons.doubleTail(); + } + return result.doubleReverse(); + } + @NonNull @Override public Double head() { @@ -67,6 +81,12 @@ public ConsList reverse() { return doubleReverse(); } + @NonNull + @Override + public ConsList map(@NonNull Function mapper) { + return ConsUtil.map(this, mapper); + } + @Override public boolean isEmpty() { return false; diff --git a/cons-list/src/main/java/io/github/nblxa/cons/IntConsList.java b/cons-list/src/main/java/io/github/nblxa/cons/IntConsList.java index be9fc14..9d7d5f3 100644 --- a/cons-list/src/main/java/io/github/nblxa/cons/IntConsList.java +++ b/cons-list/src/main/java/io/github/nblxa/cons/IntConsList.java @@ -7,6 +7,7 @@ import java.util.NoSuchElementException; import java.util.PrimitiveIterator; import java.util.Spliterator; +import java.util.function.IntUnaryOperator; import java.util.stream.IntStream; @Immutable @@ -63,4 +64,16 @@ public interface IntConsList extends ConsList { */ @NonNull IntStream intStream(); + + /** + * Eager implementation of the map method that applies mapper + * to all elements of the IntConsList. + * + * The resulting new list has the same order of elements. + * + * @param mapper the mapping function to be applied to all elements + * @return new resulting list + */ + @NonNull + IntConsList intMap(@NonNull IntUnaryOperator mapper); } diff --git a/cons-list/src/main/java/io/github/nblxa/cons/IntConsListImpl.java b/cons-list/src/main/java/io/github/nblxa/cons/IntConsListImpl.java index 617479b..a187919 100644 --- a/cons-list/src/main/java/io/github/nblxa/cons/IntConsListImpl.java +++ b/cons-list/src/main/java/io/github/nblxa/cons/IntConsListImpl.java @@ -9,6 +9,8 @@ import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.*; +import java.util.function.Function; +import java.util.function.IntUnaryOperator; import java.util.stream.IntStream; import java.util.stream.StreamSupport; @@ -49,6 +51,18 @@ public IntConsList intReverse() { return result; } + @NonNull + @Override + public IntConsList intMap(@NonNull IntUnaryOperator mapper) { + IntConsList result = ConsList.nil(); + IntConsList cons = this; + while (cons != Nil.INSTANCE) { + result = new IntConsListImpl(mapper.applyAsInt(cons.intHead()), result); + cons = cons.intTail(); + } + return result.intReverse(); + } + @NonNull @Override public Integer head() { @@ -67,6 +81,12 @@ public ConsList reverse() { return intReverse(); } + @NonNull + @Override + public ConsList map(@NonNull Function mapper) { + return ConsUtil.map(this, mapper); + } + @Override public boolean isEmpty() { return false; diff --git a/cons-list/src/main/java/io/github/nblxa/cons/LongConsList.java b/cons-list/src/main/java/io/github/nblxa/cons/LongConsList.java index c9eb589..26dc6c3 100644 --- a/cons-list/src/main/java/io/github/nblxa/cons/LongConsList.java +++ b/cons-list/src/main/java/io/github/nblxa/cons/LongConsList.java @@ -7,6 +7,7 @@ import java.util.NoSuchElementException; import java.util.PrimitiveIterator; import java.util.Spliterator; +import java.util.function.LongUnaryOperator; import java.util.stream.LongStream; @Immutable @@ -63,4 +64,16 @@ public interface LongConsList extends ConsList { */ @NonNull LongStream longStream(); + + /** + * Eager implementation of the map method that applies mapper + * to all elements of the LongConsList. + * + * The resulting new list has the same order of elements. + * + * @param mapper the mapping function to be applied to all elements + * @return new resulting list + */ + @NonNull + LongConsList longMap(@NonNull LongUnaryOperator mapper); } diff --git a/cons-list/src/main/java/io/github/nblxa/cons/LongConsListImpl.java b/cons-list/src/main/java/io/github/nblxa/cons/LongConsListImpl.java index 9d222f4..f9338f9 100644 --- a/cons-list/src/main/java/io/github/nblxa/cons/LongConsListImpl.java +++ b/cons-list/src/main/java/io/github/nblxa/cons/LongConsListImpl.java @@ -9,6 +9,8 @@ import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.*; +import java.util.function.Function; +import java.util.function.LongUnaryOperator; import java.util.stream.LongStream; import java.util.stream.StreamSupport; @@ -49,6 +51,36 @@ public LongConsList longReverse() { return result; } + @NonNull + @Override + public PrimitiveIterator.OfLong longIterator() { + return new LongConsIterator(this); + } + + @NonNull + @Override + public Spliterator.OfLong longSpliterator() { + return Spliterators.spliteratorUnknownSize(longIterator(), ConsUtil.SPLITERATOR_CHARACTERISTICS); + } + + @NonNull + @Override + public LongStream longStream() { + return StreamSupport.longStream(longSpliterator(), false); + } + + @NonNull + @Override + public LongConsList longMap(@NonNull LongUnaryOperator mapper) { + LongConsList result = ConsList.nil(); + LongConsList cons = this; + while (cons != Nil.INSTANCE) { + result = new LongConsListImpl(mapper.applyAsLong(cons.longHead()), result); + cons = cons.longTail(); + } + return result.longReverse(); + } + @NonNull @Override public Long head() { @@ -67,6 +99,12 @@ public ConsList reverse() { return longReverse(); } + @NonNull + @Override + public ConsList map(@NonNull Function mapper) { + return ConsUtil.map(this, mapper); + } + @Override public boolean isEmpty() { return false; @@ -95,24 +133,6 @@ public Spliterator spliterator() { return longSpliterator(); } - @NonNull - @Override - public PrimitiveIterator.OfLong longIterator() { - return new LongConsIterator(this); - } - - @NonNull - @Override - public Spliterator.OfLong longSpliterator() { - return Spliterators.spliteratorUnknownSize(longIterator(), ConsUtil.SPLITERATOR_CHARACTERISTICS); - } - - @NonNull - @Override - public LongStream longStream() { - return StreamSupport.longStream(longSpliterator(), false); - } - @Override public final boolean equals(Object o) { if (this == o) { diff --git a/cons-list/src/main/java/io/github/nblxa/cons/Nil.java b/cons-list/src/main/java/io/github/nblxa/cons/Nil.java index 4881c3f..e879497 100644 --- a/cons-list/src/main/java/io/github/nblxa/cons/Nil.java +++ b/cons-list/src/main/java/io/github/nblxa/cons/Nil.java @@ -6,6 +6,10 @@ import javax.annotation.concurrent.ThreadSafe; import java.io.Serializable; import java.util.*; +import java.util.function.DoubleUnaryOperator; +import java.util.function.Function; +import java.util.function.IntUnaryOperator; +import java.util.function.LongUnaryOperator; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; @@ -44,6 +48,13 @@ public Nil reverse() { return this; } + @NonNull + @Override + @SuppressWarnings("unchecked") + public Nil map(@NonNull Function mapper) { + return (Nil) this; + } + @Override public int intHead() { throw new NoSuchElementException(); @@ -89,6 +100,12 @@ public IntStream intStream() { return IntStream.empty(); } + @NonNull + @Override + public IntConsList intMap(@NonNull IntUnaryOperator mapper) { + return this; + } + @Override public long longHead() { throw new NoSuchElementException(); @@ -134,6 +151,12 @@ public LongStream longStream() { return LongStream.empty(); } + @NonNull + @Override + public LongConsList longMap(@NonNull LongUnaryOperator mapper) { + return this; + } + @Override public double doubleHead() { throw new NoSuchElementException(); @@ -179,6 +202,12 @@ public DoubleStream doubleStream() { return DoubleStream.empty(); } + @NonNull + @Override + public DoubleConsList doubleMap(@NonNull DoubleUnaryOperator mapper) { + return this; + } + @Override public boolean isEmpty() { return true; diff --git a/cons-list/src/test/java/io/github/nblxa/cons/ConsListTest.java b/cons-list/src/test/java/io/github/nblxa/cons/ConsListTest.java index a8eb9c8..bdcb5fd 100644 --- a/cons-list/src/test/java/io/github/nblxa/cons/ConsListTest.java +++ b/cons-list/src/test/java/io/github/nblxa/cons/ConsListTest.java @@ -355,4 +355,52 @@ public void consUtil() throws NoSuchMethodException { } } } + + @Test + public void map_producesExpectedResult() { + ConsList integers = list(3, 14, 12, 92, 6); + ConsList strings = integers.map(Object::toString); + assertThat(strings) + .containsExactly("3", "14", "12", "92", "6"); + } + + @Test + public void map_isEager() { + List events = new ArrayList<>(); + + list(3, 14) + .map(e -> { + events.add("Map 1 Element " + e); + return e; + }) + .map(e -> { + events.add("Map 2 Element " + e); + return e; + }); + + assertThat(events) + .containsExactly( + "Map 1 Element 3", "Map 1 Element 14", "Map 2 Element 3", "Map 2 Element 14"); + } + + @Test + public void streamMap_isLazy() { + List events = new ArrayList<>(); + + list(3, 14) + .stream() + .map(e -> { + events.add("Map 1 Element " + e); + return e; + }) + .map(e -> { + events.add("Map 2 Element " + e); + return e; + }) + .collect(ConsList.toConsCollector()); + + assertThat(events) + .containsExactly( + "Map 1 Element 3", "Map 2 Element 3", "Map 1 Element 14", "Map 2 Element 14"); + } } diff --git a/cons-list/src/test/java/io/github/nblxa/cons/DoubleConsListTest.java b/cons-list/src/test/java/io/github/nblxa/cons/DoubleConsListTest.java index 76bd331..4c2b263 100644 --- a/cons-list/src/test/java/io/github/nblxa/cons/DoubleConsListTest.java +++ b/cons-list/src/test/java/io/github/nblxa/cons/DoubleConsListTest.java @@ -319,4 +319,80 @@ public void concat_firstNullListArg_throwsException() { .hasNoCause() .hasMessage("Null concat argument at position 0"); } + + @Test + public void map_producesExpectedResult() { + ConsList doubles = doubleList(3.1d, 14.1d, 12.1d, 92.1d, 6.1d); + ConsList timesTwo = doubles.map(d -> d * 2); + assertThat(timesTwo) + .containsExactly(6.2d, 28.2d, 24.2d, 184.2d, 12.2d); + } + + @Test + public void map_isEager() { + List events = new ArrayList<>(); + + doubleList(3.1d, 14.1d) + .map(e -> { + events.add("Map 1 Element " + e); + return e; + }) + .map(e -> { + events.add("Map 2 Element " + e); + return e; + }); + + assertThat(events) + .containsExactly( + "Map 1 Element 3.1", "Map 1 Element 14.1", "Map 2 Element 3.1", "Map 2 Element 14.1"); + } + + @Test + public void doubleMap_producesExpectedResult() { + DoubleConsList doubles = doubleList(3.1d, 14.1d, 12.1d, 92.1d, 6.1d); + DoubleConsList timesTwo = doubles.doubleMap(d -> d * 2); + assertThat(timesTwo) + .containsExactly(6.2d, 28.2d, 24.2d, 184.2d, 12.2d); + } + + @Test + public void doubleMap_isEager() { + List events = new ArrayList<>(); + + doubleList(3.1d, 14.1d) + .doubleMap(e -> { + events.add("Map 1 Element " + e); + return e; + }) + .doubleMap(e -> { + events.add("Map 2 Element " + e); + return e; + }); + + assertThat(events) + .containsExactly( + "Map 1 Element 3.1", "Map 1 Element 14.1", "Map 2 Element 3.1", "Map 2 Element 14.1"); + } + + @Test + public void doubleStreamMap_isLazy() { + List events = new ArrayList<>(); + + doubleList(3.1d, 14.1d) + .doubleStream() + .map(e -> { + events.add("Map 1 Element " + e); + return e; + }) + .map(e -> { + events.add("Map 2 Element " + e); + return e; + }) + .boxed() + .collect(ConsList.toConsCollector()); + + assertThat(events) + .containsExactly( + "Map 1 Element 3.1", "Map 2 Element 3.1", "Map 1 Element 14.1", "Map 2 Element 14.1"); + } } diff --git a/cons-list/src/test/java/io/github/nblxa/cons/IntConsListTest.java b/cons-list/src/test/java/io/github/nblxa/cons/IntConsListTest.java index 3fcbefa..2b123a2 100644 --- a/cons-list/src/test/java/io/github/nblxa/cons/IntConsListTest.java +++ b/cons-list/src/test/java/io/github/nblxa/cons/IntConsListTest.java @@ -319,4 +319,80 @@ public void concat_firstNullListArg_throwsException() { .hasNoCause() .hasMessage("Null concat argument at position 0"); } + + @Test + public void map_producesExpectedResult() { + ConsList integers = intList(3, 14, 12, 92, 6); + ConsList timesTwo = integers.map(d -> d * 2); + assertThat(timesTwo) + .containsExactly(6, 28, 24, 184, 12); + } + + @Test + public void map_isEager() { + List events = new ArrayList<>(); + + intList(3, 14) + .map(e -> { + events.add("Map 1 Element " + e); + return e; + }) + .map(e -> { + events.add("Map 2 Element " + e); + return e; + }); + + assertThat(events) + .containsExactly( + "Map 1 Element 3", "Map 1 Element 14", "Map 2 Element 3", "Map 2 Element 14"); + } + + @Test + public void intMap_producesExpectedResult() { + IntConsList integers = intList(3, 14, 12, 92, 6); + IntConsList timesTwo = integers.intMap(d -> d * 2); + assertThat(timesTwo) + .containsExactly(6, 28, 24, 184, 12); + } + + @Test + public void intMap_isEager() { + List events = new ArrayList<>(); + + intList(3, 14) + .intMap(e -> { + events.add("Map 1 Element " + e); + return e; + }) + .intMap(e -> { + events.add("Map 2 Element " + e); + return e; + }); + + assertThat(events) + .containsExactly( + "Map 1 Element 3", "Map 1 Element 14", "Map 2 Element 3", "Map 2 Element 14"); + } + + @Test + public void intStreamMap_isLazy() { + List events = new ArrayList<>(); + + intList(3, 14) + .intStream() + .map(e -> { + events.add("Map 1 Element " + e); + return e; + }) + .map(e -> { + events.add("Map 2 Element " + e); + return e; + }) + .boxed() + .collect(ConsList.toConsCollector()); + + assertThat(events) + .containsExactly( + "Map 1 Element 3", "Map 2 Element 3", "Map 1 Element 14", "Map 2 Element 14"); + } } diff --git a/cons-list/src/test/java/io/github/nblxa/cons/LongConsListTest.java b/cons-list/src/test/java/io/github/nblxa/cons/LongConsListTest.java index 025907c..9868aae 100644 --- a/cons-list/src/test/java/io/github/nblxa/cons/LongConsListTest.java +++ b/cons-list/src/test/java/io/github/nblxa/cons/LongConsListTest.java @@ -319,4 +319,80 @@ public void concat_firstNullListArg_throwsException() { .hasNoCause() .hasMessage("Null concat argument at position 0"); } + + @Test + public void map_producesExpectedResult() { + ConsList longs = longList(3L, 14L, 12L, 92L, 6L); + ConsList timesTwo = longs.map(d -> d * 2); + assertThat(timesTwo) + .containsExactly(6L, 28L, 24L, 184L, 12L); + } + + @Test + public void map_isEager() { + List events = new ArrayList<>(); + + longList(3L, 14L) + .map(e -> { + events.add("Map 1 Element " + e); + return e; + }) + .map(e -> { + events.add("Map 2 Element " + e); + return e; + }); + + assertThat(events) + .containsExactly( + "Map 1 Element 3", "Map 1 Element 14", "Map 2 Element 3", "Map 2 Element 14"); + } + + @Test + public void longMap_producesExpectedResult() { + LongConsList longs = longList(3L, 14L, 12L, 92L, 6L); + LongConsList timesTwo = longs.longMap(d -> d * 2); + assertThat(timesTwo) + .containsExactly(6L, 28L, 24L, 184L, 12L); + } + + @Test + public void longMap_isEager() { + List events = new ArrayList<>(); + + longList(3L, 14L) + .longMap(e -> { + events.add("Map 1 Element " + e); + return e; + }) + .longMap(e -> { + events.add("Map 2 Element " + e); + return e; + }); + + assertThat(events) + .containsExactly( + "Map 1 Element 3", "Map 1 Element 14", "Map 2 Element 3", "Map 2 Element 14"); + } + + @Test + public void longStreamMap_isLazy() { + List events = new ArrayList<>(); + + longList(3L, 14L) + .longStream() + .map(e -> { + events.add("Map 1 Element " + e); + return e; + }) + .map(e -> { + events.add("Map 2 Element " + e); + return e; + }) + .boxed() + .collect(ConsList.toConsCollector()); + + assertThat(events) + .containsExactly( + "Map 1 Element 3", "Map 2 Element 3", "Map 1 Element 14", "Map 2 Element 14"); + } } diff --git a/cons-list/src/test/java/io/github/nblxa/cons/NilEqualsTest.java b/cons-list/src/test/java/io/github/nblxa/cons/NilEqualsTest.java index 59bf59b..19a55d2 100644 --- a/cons-list/src/test/java/io/github/nblxa/cons/NilEqualsTest.java +++ b/cons-list/src/test/java/io/github/nblxa/cons/NilEqualsTest.java @@ -4,34 +4,33 @@ import org.junit.Test; import static io.github.nblxa.cons.ConsList.*; -import static org.assertj.core.api.Assertions.assertThat; public class NilEqualsTest { @Test public void equalsHashCode_consListImpl() { - EqualsVerifier.forClass(ConsList.class) + EqualsVerifier.forClass(Nil.class) .withPrefabValues(ConsList.class, nil(), list("a", "b", "c")) .verify(); } @Test public void equalsHashCode_intConsListImpl() { - EqualsVerifier.forClass(ConsList.class) + EqualsVerifier.forClass(Nil.class) .withPrefabValues(ConsList.class, nil(), intList(1, 2, 3)) .verify(); } @Test public void equalsHashCode_longConsListImpl() { - EqualsVerifier.forClass(ConsList.class) + EqualsVerifier.forClass(Nil.class) .withPrefabValues(ConsList.class, nil(), longList(1L, 2L, 3L)) .verify(); } @Test public void equalsHashCode_doubleConsListImpl() { - EqualsVerifier.forClass(ConsList.class) + EqualsVerifier.forClass(Nil.class) .withPrefabValues(ConsList.class, nil(), doubleList(1.1d, 2.1d, 3.1d)) .verify(); } diff --git a/cons-list/src/test/java/io/github/nblxa/cons/NilTest.java b/cons-list/src/test/java/io/github/nblxa/cons/NilTest.java index 08d8080..8ccb393 100644 --- a/cons-list/src/test/java/io/github/nblxa/cons/NilTest.java +++ b/cons-list/src/test/java/io/github/nblxa/cons/NilTest.java @@ -25,6 +25,7 @@ public void testHashCode() { @Test public void testSingleton() throws NoSuchMethodException { + @SuppressWarnings("rawtypes") Constructor constructor = Nil.class.getDeclaredConstructor(); boolean isAccessible = constructor.isAccessible(); try { @@ -95,7 +96,8 @@ public void testNilDoubleIterator() { @Test public void testNilSpliterator() { Spliterator spliter = nil().spliterator(); - assertThat(spliter.getExactSizeIfKnown()).isEqualTo(0L); + assertThat(spliter.getExactSizeIfKnown()) + .isEqualTo(0L); } @Test @@ -107,13 +109,15 @@ public void testNilIntSpliterator() { @Test public void testNilLongSpliterator() { Spliterator.OfLong spliter = nil().longSpliterator(); - assertThat(spliter.getExactSizeIfKnown()).isEqualTo(0L); + assertThat(spliter.getExactSizeIfKnown()) + .isEqualTo(0L); } @Test public void testNilDoubleSpliterator() { Spliterator.OfDouble spliter = nil().doubleSpliterator(); - assertThat(spliter.getExactSizeIfKnown()).isEqualTo(0L); + assertThat(spliter.getExactSizeIfKnown()) + .isEqualTo(0L); } @Test @@ -121,7 +125,8 @@ public void testNilStream() { List list = nil() .stream() .collect(Collectors.toList()); - assertThat(list).isEmpty(); + assertThat(list) + .isEmpty(); } @Test @@ -130,7 +135,8 @@ public void testNilIntStream() { .intStream() .boxed() .collect(Collectors.toList()); - assertThat(list).isEmpty(); + assertThat(list) + .isEmpty(); } @Test @@ -139,7 +145,8 @@ public void testNilLongStream() { .longStream() .boxed() .collect(Collectors.toList()); - assertThat(list).isEmpty(); + assertThat(list) + .isEmpty(); } @Test @@ -148,30 +155,63 @@ public void testNilDoubleStream() { .doubleStream() .boxed() .collect(Collectors.toList()); - assertThat(list).isEmpty(); + assertThat(list) + .isEmpty(); } @Test public void testReverse() { ConsList nil = nil(); - assertThat(nil.reverse()).isEqualTo(nil); + assertThat(nil.reverse()) + .isEqualTo(nil); } @Test public void testIntReverse() { IntConsList nil = nil(); - assertThat(nil.intReverse()).isEqualTo(nil); + assertThat(nil.intReverse()) + .isEqualTo(nil); } @Test public void testLongReverse() { LongConsList nil = nil(); - assertThat(nil.longReverse()).isEqualTo(nil); + assertThat(nil.longReverse()) + .isEqualTo(nil); } @Test public void testDoubleReverse() { DoubleConsList nil = nil(); - assertThat(nil.doubleReverse()).isEqualTo(nil); + assertThat(nil.doubleReverse()) + .isEqualTo(nil); + } + + @Test + public void testMap() { + ConsList nil = nil(); + assertThat(nil.map(Object::toString)) + .isEqualTo(nil); + } + + @Test + public void testIntMap() { + IntConsList nil = nil(); + assertThat(nil.intMap(i -> i + 1)) + .isEqualTo(nil); + } + + @Test + public void testLongMap() { + LongConsList nil = nil(); + assertThat(nil.longMap(i -> i + 1L)) + .isEqualTo(nil); + } + + @Test + public void testDoubleMap() { + DoubleConsList nil = nil(); + assertThat(nil.doubleMap(i -> i + 1d)) + .isEqualTo(nil); } }