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 --- .../fr/epita/assistants/seq/ExtendedStream.java | 204 ++++++++++ .../src/main/java/fr/epita/assistants/seq/Seq.java | 413 +++++++++++++++++++++ 2 files changed, 617 insertions(+) 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 (limited to 'graphs/java/seq/src/main') 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(); + } +} -- cgit v1.2.3