From c9b6b9a5ca082fe7c1b6f58d7713f785a9eb6a5c Mon Sep 17 00:00:00 2001 From: Martial Simon Date: Mon, 15 Sep 2025 01:08:27 +0200 Subject: add: graphs et rushs --- graphs/java/seq/.gitignore | 38 ++ graphs/java/seq/pom.xml | 133 +++++++ .../fr/epita/assistants/seq/ExtendedStream.java | 204 ++++++++++ .../src/main/java/fr/epita/assistants/seq/Seq.java | 413 +++++++++++++++++++++ .../epita/assistants/seq/ExtendedStreamTest.java | 244 ++++++++++++ 5 files changed, 1032 insertions(+) create mode 100644 graphs/java/seq/.gitignore create mode 100644 graphs/java/seq/pom.xml create mode 100644 graphs/java/seq/src/main/java/fr/epita/assistants/seq/ExtendedStream.java create mode 100644 graphs/java/seq/src/main/java/fr/epita/assistants/seq/Seq.java create mode 100644 graphs/java/seq/src/test/java/fr/epita/assistants/seq/ExtendedStreamTest.java (limited to 'graphs/java/seq') diff --git a/graphs/java/seq/.gitignore b/graphs/java/seq/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/graphs/java/seq/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/graphs/java/seq/pom.xml b/graphs/java/seq/pom.xml new file mode 100644 index 0000000..46ba851 --- /dev/null +++ b/graphs/java/seq/pom.xml @@ -0,0 +1,133 @@ + + + 4.0.0 + fr.epita.assistants + seq + 1.0 + + + 21 + 5.9.1 + 3.13.0 + 3.5.0 + 3.1.1 + 3.1.0 + + UTF-8 + + ${project.build.directory}/surefire-reports + + + + + org.junit.jupiter + junit-jupiter + ${versions.junit} + + + org.apache.maven.surefire + surefire-junit-platform + ${versions.maven-surefire-plugin} + + + org.apache.maven + maven-compat + 3.9.8 + + + org.apache.maven + maven-plugin-api + 3.9.8 + + + org.apache.maven + maven-project + 2.2.1 + + + org.apache.maven + maven-core + 3.8.1 + + + org.apache.maven + maven-monitor + 2.2.1 + + + org.codehaus.plexus + plexus-utils + 3.0.24 + + + org.apache.maven.shared + maven-filtering + 3.3.2 + + + org.codehaus.plexus + plexus-interpolation + 1.13 + + + org.apache.maven + maven-profile + 2.2.1 + + + org.apache.maven + maven-artifact-manager + 2.2.1 + + + org.apache.maven + maven-plugin-registry + 2.2.1 + + + org.apache.maven + maven-repository-metadata + 2.2.1 + + + classworlds + classworlds + 1.1 + + + org.junit.platform + junit-platform-commons + 1.9.3 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${versions.maven-compiler-plugin} + + ${versions.java} + ${versions.java} + + + + org.apache.maven.plugins + maven-install-plugin + ${versions.maven-install-plugin} + + + + org.apache.maven.plugins + maven-surefire-plugin + ${versions.maven-surefire-plugin} + + ${surefire.reportsDirectory} + + + + + diff --git a/graphs/java/seq/src/main/java/fr/epita/assistants/seq/ExtendedStream.java b/graphs/java/seq/src/main/java/fr/epita/assistants/seq/ExtendedStream.java new file mode 100644 index 0000000..0ba5f6a --- /dev/null +++ b/graphs/java/seq/src/main/java/fr/epita/assistants/seq/ExtendedStream.java @@ -0,0 +1,204 @@ +package fr.epita.assistants.seq; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Stream; + +/** + * Extends the {@link Stream} interface, adding some very strangely lacking useful methods. + * You should use the Forwarding-Interface pattern. + *

+ * The use of infinite, unordered or parallel stream in this implementation will + * not be tested. + * + * @param the type of stream. + */ +@SuppressWarnings("unused") +public interface ExtendedStream extends Stream { + + + /** + * Creates a map out of the stream. + * In case of duplicate keys, the latest element in the original stream will overwrite the one(s) in place. + * + * @param keyMapper mapping function to extract map keys. + * @param the expected type of key. + * @return the created map. + */ + Map + toMap(final Function keyMapper); + + /** + * Creates a map out of the stream. + * In case of key duplicates, the latest element in the original stream will overwrite the one(s) in place. + * + * @param map the map to fill/update. + * @param keyMapper mapping function to extract map keys. + * @param valueMapper mapping function to extract map values. + * @param the expected type of key. + * @param the expected type of value. + * @param the complete return type. + * @return the created map. + */ + > + MAP_TYPE toMap(final MAP_TYPE map, + final Function keyMapper, + final Function valueMapper); + + /** + * Creates a map out of the stream. + * In case of duplicate keys, the latest element in the original stream will overwrite the one(s) in place. + * + * @param keyMapper mapping function to extract map keys. + * @param valueMapper mapping function to extract map values. + * @param the expected type of key. + * @param the expected type of value. + * @return the created map. + */ + + Map toMap(final Function keyMapper, + final Function valueMapper); + + /** + * Converts the stream to a list. + * + * @return the created list. + */ + List toList(); + + /** + * Dumps the content of the stream to the given list. + * + * @param list the list to dump values to. + * @param the exact type of list. + * @return the updated list. + */ + > LIST toList(final LIST list); + + /** + * Converts the stream to a set. + * + * @return the built set. + */ + Set toSet(); + + /** + * Dumps the content of the stream to the given set. + * + * @param set the set to update + * @param the set type. + * @return the updated set. + */ + > SET toSet(final SET set); + + /** + * Creates a stream of pairs of the content of the stream and values produced by a supplier. + * + * @param supplier the value supplier. + * @param the type of associated values. + * @return the built stream. + */ + + ExtendedStream> associate(final Supplier supplier); + + /** + * Creates a stream of pairs of the content of the stream and values produces by another stream. + * Once any of the two streams is closed, the produced stream is complete, regardless of potential values remaining + * in the other stream. + * + * @param supplier the value supplier. + * @param the type of associated values. + * @return the built stream. + */ + + ExtendedStream> associate(final Stream supplier); + + /** + * Prints the element of the stream on the standard output. + * + * @return this. + */ + ExtendedStream print(); + + /** + * Adds the content of the given stream to the current stream and returns it as a new one. + * + * @param stream the stream to add. + * @return a new stream containing the current one then the given one. + */ + ExtendedStream plus(final Stream stream); + + /** + * Builds a string by joining the string representation of all contained values, interspersed with the given string + * delimiter. + * + * @param delimiter the delimiter string. + * @return the built {@link String}. + */ + String join(final String delimiter); + + /** + * Builds a string by joining the string representation of all contained values. + * + * @return the built {@link String}. + */ + String join(); + + /** + * Builds a pair of streams by partitioning the current one using the given pivot function. + * + * @param pivot the function to segregate the values of the given stream. + * @param type of partition key. + * @return the pair of created streams. + */ + + ExtendedStream>> + partition(final Function pivot); + + /** + * A utility class representing a pair. + * + * @param the first value type. + * @param the second value type. + */ + @SuppressWarnings("WeakerAccess") + class Pair { + /** + * The first value. + */ + public final FIRST_TYPE first; + + /** + * The second value. + */ + public final SECOND_TYPE second; + + /** + * Default CTor. + * + * @param first value of the same name. + * @param second value of the same name. + */ + public Pair(final FIRST_TYPE first, final SECOND_TYPE second) { + this.first = first; + this.second = second; + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) return false; + if (!obj.getClass().equals(Pair.class)) return false; + final Pair pair = (Pair) obj; + return Objects.equals(first, pair.first) && Objects.equals(second, pair.second); + } + + @Override + public int hashCode() { + return Objects.hash(first, second); + } + } +} diff --git a/graphs/java/seq/src/main/java/fr/epita/assistants/seq/Seq.java b/graphs/java/seq/src/main/java/fr/epita/assistants/seq/Seq.java new file mode 100644 index 0000000..31e5cab --- /dev/null +++ b/graphs/java/seq/src/main/java/fr/epita/assistants/seq/Seq.java @@ -0,0 +1,413 @@ +package fr.epita.assistants.seq; + +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +public interface Seq extends ExtendedStream { + Stream giveStream(); + + static Seq of(Stream stream) { + return () -> stream; + } + + static Seq of(List list) { + return list::stream; + } + + static Seq of(ELEMENT_TYPE... values) { + List vals = new ArrayList<>(Arrays.asList(values)); + return vals::stream; + } + + /** + * Creates a map out of the stream. + * In case of duplicate keys, the latest element in the original stream will overwrite the one(s) in place. + * + * @param keyMapper mapping function to extract map keys. + * @param the expected type of key. + * @return the created map. + */ + default Map + toMap(final Function keyMapper) { + Map map = new HashMap<>(); + giveStream().forEach(e -> map.put(keyMapper.apply(e), e)); + return map; + } + + /** + * Creates a map out of the stream. + * In case of key duplicates, the latest element in the original stream will overwrite the one(s) in place. + * + * @param map the map to fill/update. + * @param keyMapper mapping function to extract map keys. + * @param valueMapper mapping function to extract map values. + * @param the expected type of key. + * @param the expected type of value. + * @param the complete return type. + * @return the created map. + */ + default > + MAP_TYPE toMap(final MAP_TYPE map, + final Function keyMapper, + final Function valueMapper) { + giveStream().forEach(e -> map.put(keyMapper.apply(e), valueMapper.apply(e))); + return map; + } + + /** + * Creates a map out of the stream. + * In case of duplicate keys, the latest element in the original stream will overwrite the one(s) in place. + * + * @param keyMapper mapping function to extract map keys. + * @param valueMapper mapping function to extract map values. + * @param the expected type of key. + * @param the expected type of value. + * @return the created map. + */ + default + Map toMap(final Function keyMapper, + final Function valueMapper) { + Map map = new HashMap<>(); + giveStream().forEach(e -> map.put(keyMapper.apply(e), valueMapper.apply(e))); + return map; + } + + @Override + public default Stream filter(Predicate predicate) { + return giveStream().filter(predicate); + } + + @Override + public default Stream map(Function mapper) { + return giveStream().map(mapper); + } + + @Override + public default IntStream mapToInt(ToIntFunction mapper) { + return giveStream().mapToInt(mapper); + } + + @Override + public default LongStream mapToLong(ToLongFunction mapper) { + return giveStream().mapToLong(mapper); + } + + @Override + public default DoubleStream mapToDouble(ToDoubleFunction mapper) { + return giveStream().mapToDouble(mapper); + } + + @Override + public default Stream flatMap(Function> mapper) { + return giveStream().flatMap(mapper); + } + + @Override + public default IntStream flatMapToInt(Function mapper) { + return giveStream().flatMapToInt(mapper); + } + + @Override + public default LongStream flatMapToLong(Function mapper) { + return giveStream().flatMapToLong(mapper); + } + + @Override + public default DoubleStream flatMapToDouble(Function mapper) { + return giveStream().flatMapToDouble(mapper); + } + + @Override + public default Stream distinct() { + return giveStream().distinct(); + } + + @Override + public default Stream sorted() { + return giveStream().sorted(); + } + + @Override + public default Stream sorted(Comparator comparator) { + return giveStream().sorted(comparator); + } + + @Override + public default Stream peek(Consumer action) { + return giveStream().peek(action); + } + + @Override + public default Stream limit(long maxSize) { + return giveStream().limit(maxSize); + } + + @Override + public default Stream skip(long n) { + return giveStream().skip(n); + } + + @Override + public default void forEach(Consumer action) { + giveStream().forEach(action); + } + + @Override + public default void forEachOrdered(Consumer action) { + giveStream().forEachOrdered(action); + } + + @Override + public default Object[] toArray() { + return giveStream().toArray(); + } + + @Override + public default A[] toArray(IntFunction generator) { + return giveStream().toArray(generator); + } + + @Override + public default ELEMENT_TYPE reduce(ELEMENT_TYPE identity, BinaryOperator accumulator) { + return giveStream().reduce(identity, accumulator); + } + + @Override + public default Optional reduce(BinaryOperator accumulator) { + return giveStream().reduce(accumulator); + } + + @Override + public default U reduce(U identity, BiFunction accumulator, BinaryOperator combiner) { + return giveStream().reduce(identity, accumulator, combiner); + } + + @Override + public default R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner) { + return giveStream().collect(supplier, accumulator, combiner); + } + + @Override + public default R collect(Collector collector) { + return giveStream().collect(collector); + } + + /** + * Converts the stream to a list. + * + * @return the created list. + */ + default List toList() { + return giveStream().toList(); + } + + @Override + public default Optional min(Comparator comparator) { + return giveStream().min(comparator); + } + + @Override + public default Optional max(Comparator comparator) { + return giveStream().max(comparator); + } + + @Override + public default long count() { + return giveStream().count(); + } + + @Override + public default boolean anyMatch(Predicate predicate) { + return giveStream().anyMatch(predicate); + } + + @Override + public default boolean allMatch(Predicate predicate) { + return giveStream().allMatch(predicate); + } + + @Override + public default boolean noneMatch(Predicate predicate) { + return giveStream().noneMatch(predicate); + } + + @Override + public default Optional findFirst() { + return giveStream().findFirst(); + } + + @Override + public default Optional findAny() { + return giveStream().findAny(); + } + + /** + * Dumps the content of the stream to the given list. + * + * @param list the list to dump values to. + * @param the exact type of list. + * @return the updated list. + */ + default > LIST toList(final LIST list) { + giveStream().forEach(list::add); + return list; + } + + /** + * Converts the stream to a set. + * + * @return the built set. + */ + default Set toSet() { + return giveStream().collect(Collectors.toSet()); + } + + /** + * Dumps the content of the stream to the given set. + * + * @param set the set to update + * @param the set type. + * @return the updated set. + */ + default > SET toSet(final SET set) { + giveStream().forEach(set::add); + return set; + } + + /** + * Creates a stream of pairs of the content of the stream and values produced by a supplier. + * + * @param supplier the value supplier. + * @param the type of associated values. + * @return the built stream. + */ + default + ExtendedStream> associate(final Supplier supplier) { + return Seq.of(giveStream().map(e -> new Pair(e, supplier.get()))); + } + + /** + * Creates a stream of pairs of the content of the stream and values produces by another stream. + * Once any of the two streams is closed, the produced stream is complete, regardless of potential values remaining + * in the other stream. + * + * @param supplier the value supplier. + * @param the type of associated values. + * @return the built stream. + */ + default + ExtendedStream> associate(final Stream supplier) { + List elements = giveStream().toList(); + List assocs = supplier.toList(); + return Seq.of(IntStream.range(0, Math.min(elements.size(), + assocs.size())).mapToObj(i -> new Pair(elements.get(i), assocs.get(i)))); + } + + /** + * Prints the element of the stream on the standard output. + * + * @return this. + */ + default ExtendedStream print() { + return (ExtendedStream) giveStream().peek(System.out::println); + } + + /** + * Adds the content of the given stream to the current stream and returns it as a new one. + * + * @param stream the stream to add. + * @return a new stream containing the current one then the given one. + */ + default ExtendedStream plus(final Stream stream) { + return Seq.of(Stream.concat(giveStream(), stream)); + } + + /** + * Builds a string by joining the string representation of all contained values, interspersed with the given string + * delimiter. + * + * @param delimiter the delimiter string. + * @return the built {@link String}. + */ + default String join(final String delimiter) { + return giveStream().map(ELEMENT_TYPE::toString).collect(Collectors.joining(delimiter)); + } + + /** + * Builds a string by joining the string representation of all contained values. + * + * @return the built {@link String}. + */ + default String join() { + return giveStream().map(ELEMENT_TYPE::toString).collect(Collectors.joining()); + } + + /** + * Builds a pair of streams by partitioning the current one using the given pivot function. + * + * @param pivot the function to segregate the values of the given stream. + * @param type of partition key. + * @return the pair of created streams. + */ + default + ExtendedStream>> + partition(final Function pivot) { + Map> map = new HashMap<>(); + giveStream().forEach(e -> { + KEY_TYPE key = pivot.apply(e); + List assoc = new ArrayList<>(); + if (map.containsKey(key)) { + assoc.addAll(map.get(key)); + } + assoc.add(e); + map.put(key, assoc); + }); + List>> list = new ArrayList<>(); + for (KEY_TYPE key : map.keySet()) { + list.add(new Pair<>(key, Seq.of(map.get(key).stream()))); + } + return Seq.of(list.stream()); + } + + @Override + public default Iterator iterator() { + return giveStream().iterator(); + } + + @Override + public default Spliterator spliterator() { + return giveStream().spliterator(); + } + + @Override + public default boolean isParallel() { + return giveStream().isParallel(); + } + + @Override + public default Stream sequential() { + return giveStream().sequential(); + } + + @Override + public default Stream parallel() { + return giveStream().parallel(); + } + + @Override + public default Stream unordered() { + return giveStream().unordered(); + } + + @Override + public default Stream onClose(Runnable closeHandler) { + return giveStream().onClose(closeHandler); + } + + @Override + public default void close() { + giveStream().close(); + } +} diff --git a/graphs/java/seq/src/test/java/fr/epita/assistants/seq/ExtendedStreamTest.java b/graphs/java/seq/src/test/java/fr/epita/assistants/seq/ExtendedStreamTest.java new file mode 100644 index 0000000..b0bb911 --- /dev/null +++ b/graphs/java/seq/src/test/java/fr/epita/assistants/seq/ExtendedStreamTest.java @@ -0,0 +1,244 @@ +package fr.epita.assistants.seq; + +import java.lang.reflect.Modifier; +import java.time.Duration; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; + +import fr.epita.assistants.seq.ExtendedStream.Pair; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class ExtendedStreamTest { + + private static ExtendedStream ctor(final List values) { + // FIXME: replace by your own implementation. + return Seq.of(values); + } + + private static ExtendedStream ctor(final TYPE... values) { + // FIXME: replace by your own implementation. + return Seq.of(values); + } + + private static ExtendedStream ctor(final Stream values) { + // FIXME: replace by your own implementation. + return Seq.of(values); + } + + private static DummyObject dummy(final int id, final String name) { + return new DummyObject(id, name); + } + + @Test + public void isSeqAnInterface() throws ClassNotFoundException { + Class seqClass = Class.forName("fr.epita.assistants.seq.Seq"); + int modifiers = seqClass.getModifiers(); + boolean isInterface = Modifier.isInterface(modifiers); + assertTrue(isInterface, "Seq must be an interface"); + } + + @Test + public void toMapKeyValue() { + assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { + final ExtendedStream es = ctor(dummy(1, "1"), dummy(2, "2"), dummy(2, "4"), dummy(3, "3")); + final Map map = es.toMap(DummyObject::getId, DummyObject::getName); + assertEquals(3, map.size()); + assertEquals("1", map.get(1)); + assertEquals("4", map.get(2)); + assertEquals("3", map.get(3)); + }); + } + + @Test + public void toMapKeyValueMap() { + assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { + final ExtendedStream es = ctor(dummy(1, "1"), dummy(2, "2"), dummy(2, "4"), dummy(3, "3")); + final Map source = new HashMap<>(); + source.put(42, new DummyObject(42, "me")); + final Map map = es.toMap(source, DummyObject::getId, it -> it); + assertEquals(4, map.size()); + assertEquals("1", map.get(1).name); + assertEquals("4", map.get(2).name); + assertEquals("3", map.get(3).name); + assertEquals("me", map.get(42).name); + }); + } + + @Test + public void toMapKey() { + assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { + final ExtendedStream es = ctor(dummy(1, "1"), dummy(2, "2"), dummy(2, "4"), dummy(3, "3")); + final Map map = es.toMap(DummyObject::getId); + assertEquals(3, map.size()); + assertEquals("1", map.get(1).name); + assertEquals("4", map.get(2).name); + assertEquals("3", map.get(3).name); + }); + } + + + @Test + public void toList() { + assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { + final ExtendedStream es = ctor(dummy(1, "1"), dummy(2, "2"), dummy(2, "4"), dummy(3, "3")); + final List list = es.toList(); + assertEquals(4, list.size()); + assertEquals("1", list.get(0).name); + assertEquals("2", list.get(1).name); + assertEquals("4", list.get(2).name); + assertEquals("3", list.get(3).name); + + }); + } + + @Test + public void toListWithList() { + assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { + final ExtendedStream es = ctor(dummy(1, "1"), dummy(2, "2"), dummy(2, "4"), dummy(3, "3")); + final List source = new ArrayList<>(); + source.add(new DummyObject(42, "me")); + final List list = es.toList(source); + assertEquals(5, list.size()); + assertEquals("me", list.get(0).name); + assertEquals("1", list.get(1).name); + assertEquals("2", list.get(2).name); + assertEquals("4", list.get(3).name); + assertEquals("3", list.get(4).name); + }); + } + + @Test + public void toSet() { + assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { + final ExtendedStream es = ctor(1, 2, 2, 3); + final Set set = es.toSet(); + assertEquals(3, set.size()); + assertTrue(set.contains(1)); + assertTrue(set.contains(2)); + assertTrue(set.contains(3)); + }); + } + + @Test + public void toSetWithSet() { + assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { + final ExtendedStream es = ctor(1, 2, 2, 3); + final Set source = new HashSet<>(); + source.add(1); + source.add(2); + source.add(42); + final Set set = es.toSet(source); + assertEquals(4, set.size()); + assertTrue(set.contains(1)); + assertTrue(set.contains(2)); + assertTrue(set.contains(3)); + assertTrue(set.contains(42)); + }); + } + + @Test + public void associateWithSupplier() { + assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { + final ExtendedStream es = ctor("a", "b", "c"); + final List> list = es.associate(new Increment()).toList(); + + assertEquals(3, list.size()); + assertEquals(new Pair<>("a", 0), list.get(0)); + assertEquals(new Pair<>("b", 1), list.get(1)); + assertEquals(new Pair<>("c", 2), list.get(2)); + + + }); + } + + @Test + public void associateWithStream() { + assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { + final ExtendedStream es = ctor("a", "b", "c"); + final List> list = es.associate(ctor(0, 1, 2, 3, 4, 5)).toList(); + + assertEquals(3, list.size()); + assertEquals(new Pair<>("a", 0), list.get(0)); + assertEquals(new Pair<>("b", 1), list.get(1)); + assertEquals(new Pair<>("c", 2), list.get(2)); + }); + } + + @Test + public void plus() { + assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { + final ExtendedStream es = ctor("a", "b", "c").plus(ctor("d", "e", "f")); + assertEquals("abcdef", es.join()); + }); + } + + @Test + public void join() { + assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { + final ExtendedStream es = ctor("a", "b", "c", "d", "e", "f"); + assertEquals("abcdef", es.join()); + }); + } + + @Test + public void joinWithDelimiter() { + assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { + final ExtendedStream es = ctor("a", "b", "c", "d", "e", "f"); + assertEquals("a-b-c-d-e-f", es.join("-")); + }); + } + + @Test + public void partition() { + assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { + final ExtendedStream es = ctor(0, 1, 2, 3, 4, 5, 6, 7); + final ExtendedStream>> partitions = es.partition(val -> val % 2 == 0); + final List>> list = partitions.toList(); + + + assertEquals(list.get(0).first ? "0246" : "1357", list.get(0).second.join()); + assertEquals(list.get(0).first ? "1357" : "0246", list.get(1).second.join()); + }); + } + + static class DummyObject { + public final Integer id; + public final String name; + + public DummyObject(final Integer id, final String name) { + this.id = id; + this.name = name; + } + + public Integer getId() { + return id; + } + + public String getName() { + return name; + } + } + + + static class Increment implements Supplier { + private int increment = 0; + + @Override + public Integer get() { + return increment++; + } + } +} -- cgit v1.2.3