001/*
002 * ============================================================================
003 * Copyright © 2014 by Alexis Cartier, Dominic Fox.
004 * All Rights Reserved.
005 * ============================================================================
006 * The MIT License (MIT)
007 *
008 * Permission is hereby granted, free of charge, to any person obtaining a copy
009 * of this software and associated documentation files (the "Software"), to
010 * deal in the Software without restriction, including without limitation the
011 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
012 * sell copies of the Software, and to permit persons to whom the Software is
013 * furnished to do so, subject to the following conditions:
014 *
015 * The above copyright notice and this permission notice shall be included in
016 * all copies or substantial portions of the Software.
017 *
018 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
019 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
020 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
021 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
022 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
023 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
024 * IN THE SOFTWARE.
025 */
026
027package org.tquadrat.foundation.stream;
028
029import static java.util.stream.Collectors.groupingBy;
030import static java.util.stream.Collectors.mapping;
031import static java.util.stream.Collectors.toMap;
032import static org.apiguardian.api.API.Status.STABLE;
033
034import java.util.AbstractMap.SimpleImmutableEntry;
035import java.util.Arrays;
036import java.util.Collection;
037import java.util.Comparator;
038import java.util.List;
039import java.util.Map;
040import java.util.Map.Entry;
041import java.util.function.BiConsumer;
042import java.util.function.BiFunction;
043import java.util.function.BiPredicate;
044import java.util.function.BinaryOperator;
045import java.util.function.Consumer;
046import java.util.function.Function;
047import java.util.function.Predicate;
048import java.util.stream.Collectors;
049import java.util.stream.Stream;
050
051import org.apiguardian.api.API;
052import org.tquadrat.foundation.annotation.ClassVersion;
053import org.tquadrat.foundation.stream.internal.DefaultMapStream;
054
055/**
056 *  A stream of
057 *  {@link java.util.Map.Entry Map.Entry<K,V>}.
058 *
059 *  @param  <K> The type of the map keys.
060 *  @param  <V> The type of the map values.
061 *
062 *  @author Alexis Cartier (alexcrt)
063 *  @author Dominic Fox
064 *  @modified Thomas Thrien - thomas.thrien@tquadrat.org
065 *  @version $Id: MapStream.java 1060 2023-09-24 19:21:40Z tquadrat $
066 *  @since 0.0.7
067 *
068 *  @UMLGraph.link
069 */
070@SuppressWarnings( "ClassWithTooManyMethods" )
071@ClassVersion( sourceVersion = "$Id: MapStream.java 1060 2023-09-24 19:21:40Z tquadrat $" )
072@API( status = STABLE, since = "0.0.7" )
073public interface MapStream<K,V> extends Stream<Entry<K,V>>
074{
075        /*---------*\
076    ====** Methods **==========================================================
077        \*---------*/
078    /**
079     *  Returns a
080     *  {@link Map}
081     *  from the stream. If there are identical keys in the stream,
082     *  {@link #mergeKeys()}
083     *  should be called before. Alternatively,
084     *  {@link #collect(BinaryOperator)}
085     *  could be used.
086     *
087     *  @return A map from the values of the stream.
088     */
089    public default Map<K,V> collect() { return collect( toMap( Entry::getKey, Entry::getValue ) ); }
090
091    /**
092     *  Returns a
093     *  {@link Map}
094     *  from the stream. If there are similar keys in the stream, the merge
095     *  function will be applied to merge the values of those keys.
096     *
097     *  @param  mergeFunction   The function that is used to merge the values
098     *      with identical keys.
099     *  @return A map from the values of the stream.
100     */
101    public default Map<K,V> collect( final BinaryOperator<V> mergeFunction ) { return collect( toMap( Entry::getKey, Entry::getValue, mergeFunction ) ); }
102
103    /**
104     *  {@inheritDoc}
105     */
106    @Override
107    public MapStream<K,V> distinct();
108
109    /**
110     *  Returns a stream consisting only of the values of underlying map for
111     *  this {@code MapStream}.<br>
112     *  <br>This is an intermediate operation.
113     *
114     * @return The new stream.
115     */
116    public default Stream<V> dropKeys() { return map( Entry::getValue ); }
117
118    /**
119     *  Returns a stream consisting only of the keys of underlying map for
120     *  this {@code MapStream}.<br>
121     *  <br>This is an intermediate operation.
122     *
123     * @return The new stream.
124     */
125    public default Stream<K> dropValues() { return map( Entry::getKey ); }
126
127    /**
128     *  {@inheritDoc}
129     */
130    @Override
131    public MapStream<K,V> filter( Predicate<? super Entry<K,V>> predicate );
132
133    /**
134     *  Returns a stream consisting of the elements of this stream that match
135     *  the given predicate.<br>
136     *  <br>This is an intermediate operation.
137     *
138     *  @param  predicate   A non-interfering, stateless predicate to apply to
139     *      each element to determine if it should be included.
140     *  @return The new stream.
141     *
142     *  @see #filter(Predicate)
143     */
144    public default MapStream<K,V> filter( final BiPredicate<? super K, ? super V> predicate )
145    {
146        return filter( entry -> predicate.test( entry.getKey(), entry.getValue() ) );
147    }   //  filter()
148
149    /**
150     *  Performs an action for each entry of the
151     *  {@link Map}
152     *  that was used to construct this stream.<br>
153     *  <br>This is a terminal operation.<br>
154     *  <br>The behaviour of this operation is explicitly nondeterministic. For
155     *  parallel stream pipelines, this operation does <em>not</em> guarantee
156     *  to respect the encounter order of the stream, as doing so would
157     *  sacrifice the benefit of parallelism. For any given element, the action
158     *  may be performed at whatever time and in whatever thread the library
159     *  chooses. If the action accesses shared state, it is responsible for
160     *  providing the required synchronisation.
161     *
162     *  @param  action  A non-interfering action to perform on the entries.
163     */
164    public default void forEach( final BiConsumer<K,V> action )
165    {
166        forEach( entry -> action.accept( entry.getKey(), entry.getValue() ) );
167    }   //  forEach()
168
169    /**
170     * Returns a {@code MapStream} from which the key and values are reversed.
171     *
172     * @return A new map stream.
173     */
174    public default MapStream<V,K> inverseMapping()
175    {
176        final MapStream<V,K> retValue = new DefaultMapStream<>( map( e -> new SimpleImmutableEntry<>( e.getValue(), e.getKey() ) ) );
177
178        //---* Done *----------------------------------------------------------
179        return retValue;
180    }   //  inverseMapping()
181
182    /**
183     *  {@inheritDoc}
184     */
185    @Override
186    public MapStream<K,V> limit( final long limit );
187
188    /**
189     *  Returns a stream consisting of the results of applying the given
190     *  function to the elements of this stream.<br>
191     *  <br>This is an intermediate operation.
192     *
193     *  @param  <R> The element type of the new stream.
194     *  @param  mapper  A non-interfering, stateless function to apply to each
195     *      element.
196     * @return The new stream.
197     */
198    public default <R> Stream<R> map( final BiFunction<K,V,? extends R> mapper )
199    {
200        return map( e -> mapper.apply( e.getKey(), e.getValue() ) );
201    }   //  map()
202
203    /**
204     *  <p>{@summary Applies the mapping for each key and value in the
205     *  map.}</p>
206     *  <p>If the mapping function is not bijective for the keys,
207     *  {@link #mergeKeys()}
208     *  or
209     *  {@link #mergeKeys(BinaryOperator)}
210     *  needs to be called before, or a merge function has to be provided
211     *  when calling
212     *  {@link #collect(BinaryOperator) collect()}.</p>
213     *
214     *  @param  <K1> The type of the map keys.
215     *  @param  <V1> The type of the map values.
216     *  @param  keyMapper   The key mapping to be applied.
217     *  @param  valueMapper The value mapping to be applied.
218     *  @return A new map stream.
219     */
220    public default <K1,V1> MapStream<K1,V1> mapEntries( final Function<? super K,? extends K1> keyMapper, final Function<? super V,? extends V1> valueMapper )
221    {
222        final MapStream<K1,V1> retValue = new DefaultMapStream<>( map( e -> new SimpleImmutableEntry<>( keyMapper.apply( e.getKey() ), valueMapper.apply( e.getValue() ) ) ) );
223
224        //---* Done *----------------------------------------------------------
225        return retValue;
226    }   //  mapEntries()
227
228    /**
229     *  Applies the mapping for each key in the map. If the mapping function is
230     *  not bijective,
231     *  {@link #mergeKeys()}
232     *  or
233     *  {@link #mergeKeys(BinaryOperator)}
234     *  needs to be called before, or a merge function has to be provided
235     *  when calling
236     *  {@link #collect(BinaryOperator) collect()}.
237     *
238     *  @param  <K1> The type of the map keys.
239     *  @param  mapper  The key mapping to be applied.
240     *  @return A new map stream.
241     */
242    public default <K1> MapStream<K1,V> mapKeys( final Function<? super K,? extends K1> mapper )
243    {
244        final MapStream<K1,V> retValue = new DefaultMapStream<>( map( e -> new SimpleImmutableEntry<>( mapper.apply( e.getKey() ), e.getValue() ) ) );
245
246        //---* Done *----------------------------------------------------------
247        return retValue;
248    }   //  mapKeys()
249
250    /**
251     *  Applies the mapping for each value in the map.
252     *
253     *  @param  <V1> The type of the map values.
254     *  @param  mapper  The value mapping to be applied.
255     *  @return A new map stream.
256     */
257    public default <V1> MapStream<K,V1> mapValues( final Function<? super V,? extends V1> mapper )
258    {
259        final MapStream<K,V1> retValue = new DefaultMapStream<>( map( e -> new SimpleImmutableEntry<>( e.getKey(), mapper.apply( e.getValue() ) ) ) );
260
261        //---* Done *----------------------------------------------------------
262        return retValue;
263    }   //  mapValues()
264
265    /**
266     *  Merges the keys of the stream into a new stream.
267     *
268     *  @return A new map stream.
269     */
270    public default MapStream<K,List<V>> mergeKeys() { return of( collect( groupingBy( Entry::getKey, mapping( Entry::getValue, Collectors.toList() ) ) ) ); }
271
272    /**
273     *  Merges keys of the stream into a new stream with the provided merge
274     *  function.
275     *
276     *  @param  mergeFunction   The merge function.
277     *  @return A new map stream.
278     */
279    public default MapStream<K,V> mergeKeys( final BinaryOperator<V> mergeFunction ) { return of( collect( mergeFunction ) ); }
280
281    /**
282     *  Factory for a {@code MapStream<K,V>}; constructs a stream from a single
283     *  key-value pair.
284     *
285     *  @param  <K> The type of the map keys.
286     *  @param  <V> The type of the map values.
287     *  @param  key The key.
288     *  @param  value   The value.
289     *  @return A new {@code MapStream<K,V>}.
290     */
291    @API( status = STABLE, since = "0.0.4" )
292    public static <K,V> MapStream<K,V> of( final K key, final V value )
293    {
294        final MapStream<K,V> retValue = new DefaultMapStream<>( Stream.of( new SimpleImmutableEntry<>( key, value ) ) );
295
296        //---* Done *----------------------------------------------------------
297        return retValue;
298    }   //  of()
299
300    /**
301     *  Factory for a {@code MapStream<K,V>}; constructs a stream from two
302     *  key-value pairs
303     *
304     *  @param  <K> The type of the map keys.
305     *  @param  <V> The type of the map values.
306     *  @param  key1    The first key.
307     *  @param  value1  The first value.
308     *  @param  key2    The second key.
309     *  @param  value2  The second value.
310     *  @return A new {@code MapStream<K,V>}.
311     */
312    @API( status = STABLE, since = "0.0.4" )
313    public static <K,V> MapStream<K,V> of( final K key1, final V value1, final K key2, final V value2 )
314    {
315        final MapStream<K,V> retValue = new DefaultMapStream<>(
316            Stream.of(
317                new SimpleImmutableEntry<>( key1, value1 ),
318                new SimpleImmutableEntry<>( key2, value2 ) ) );
319
320        //---* Done *----------------------------------------------------------
321        return retValue;
322    }   //  of()
323
324    /**
325     *  Factory for a {@code MapStream<K,V>}; constructs a stream from three
326     *  key-value pairs
327     *
328     *  @param  <K> The type of the map keys.
329     *  @param  <V> The type of the map values.
330     *  @param  key1    The first key.
331     *  @param  value1  The first value.
332     *  @param  key2    The second key.
333     *  @param  value2  The second value.
334     *  @param  key3    The third key.
335     *  @param  value3  The third value.
336     *  @return A new {@code MapStream<K,V>}.
337     */
338    @SuppressWarnings( "MethodWithTooManyParameters" )
339    @API( status = STABLE, since = "0.0.4" )
340    public static <K,V> MapStream<K,V> of( final K key1, final V value1, final K key2, final V value2, final K key3, final V value3 )
341    {
342        final MapStream<K,V> retValue = new DefaultMapStream<>(
343            Stream.of(
344                new SimpleImmutableEntry<>( key1, value1 ),
345                new SimpleImmutableEntry<>( key2, value2 ),
346                new SimpleImmutableEntry<>( key3, value3 ) ) );
347
348        //---* Done *----------------------------------------------------------
349        return retValue;
350    }   //  of()
351
352    /**
353     *  Factory for a {@code MapStream<K,V>}; constructs a stream from four
354     *  key-value pairs
355     *
356     *  @param  <K> The type of the map keys.
357     *  @param  <V> The type of the map values.
358     *  @param  key1    The first key.
359     *  @param  value1  The first value.
360     *  @param  key2    The second key.
361     *  @param  value2  The second value.
362     *  @param  key3    The third key.
363     *  @param  value3  The third value.
364     *  @param  key4    The third key.
365     *  @param  value4  The third value.
366     *  @return A new {@code MapStream<K,V>}.
367     */
368    @SuppressWarnings( "MethodWithTooManyParameters" )
369    @API( status = STABLE, since = "0.0.4" )
370    public static <K,V> MapStream<K,V> of( final K key1, final V value1, final K key2, final V value2, final K key3, final V value3, final K key4, final V value4 )
371    {
372        final MapStream<K,V> retValue = new DefaultMapStream<>(
373            Stream.of(
374                new SimpleImmutableEntry<>( key1, value1 ),
375                new SimpleImmutableEntry<>( key2, value2 ),
376                new SimpleImmutableEntry<>( key3, value3 ),
377                new SimpleImmutableEntry<>( key4, value4 ) ) );
378
379        //---* Done *----------------------------------------------------------
380        return retValue;
381    }   //  of()
382
383    /**
384     *  Factory for a {@code MapStream<K,V>}; constructs a stream from five
385     *  key-value pairs
386     *
387     *  @param  <K> The type of the map keys.
388     *  @param  <V> The type of the map values.
389     *  @param  key1    The first key.
390     *  @param  value1  The first value.
391     *  @param  key2    The second key.
392     *  @param  value2  The second value.
393     *  @param  key3    The third key.
394     *  @param  value3  The third value.
395     *  @param  key4    The third key.
396     *  @param  value4  The third value.
397     *  @param  key5    The third key.
398     *  @param  value5  The third value.
399     *  @return A new {@code MapStream<K,V>}.
400     */
401    @SuppressWarnings( "MethodWithTooManyParameters" )
402    @API( status = STABLE, since = "0.0.4" )
403    public static <K,V> MapStream<K,V> of( final K key1, final V value1, final K key2, final V value2, final K key3, final V value3, final K key4, final V value4, final K key5, final V value5 )
404    {
405        final MapStream<K,V> retValue = new DefaultMapStream<>(
406            Stream.of(
407                new SimpleImmutableEntry<>( key1, value1 ),
408                new SimpleImmutableEntry<>( key2, value2 ),
409                new SimpleImmutableEntry<>( key3, value3 ),
410                new SimpleImmutableEntry<>( key4, value4 ),
411                new SimpleImmutableEntry<>( key5, value5 ) ) );
412
413        //---* Done *----------------------------------------------------------
414        return retValue;
415    }   //  of()
416
417    /**
418     *  Factory for a {@code MapStream<K,V>}; constructs a stream from some
419     *  key-value pairs
420     *
421     *  @param  <K> The type of the map keys.
422     *  @param  <V> The type of the map values.
423     *  @param  nvps    The key-value-pairs.
424     *  @return A new {@code MapStream<K,V>}.
425     */
426    @API( status = STABLE, since = "0.0.4" )
427    @SafeVarargs
428    public static <K,V> MapStream<K,V> of( final Map.Entry<K,V>... nvps )
429    {
430        final MapStream<K,V> retValue = new DefaultMapStream<>( Arrays.stream( nvps ) );
431
432        //---* Done *----------------------------------------------------------
433        return retValue;
434    }   //  of()
435
436    /**
437     *  Factory for a {@code MapStream<K,V>}; constructs a stream from a
438     *  {@link Collection}
439     *  of key-value pairs
440     *
441     *  @param  <K> The type of the map keys.
442     *  @param  <V> The type of the map values.
443     *  @param  nvps    The key-value-pairs.
444     *  @return A new {@code MapStream<K,V>}.
445     */
446    @API( status = STABLE, since = "0.0.4" )
447    public static <K,V> MapStream<K,V> of( final Collection<Map.Entry<K,V>> nvps )
448    {
449        final MapStream<K,V> retValue = new DefaultMapStream<>( nvps.stream() );
450
451        //---* Done *----------------------------------------------------------
452        return retValue;
453    }   //  of()
454
455    /**
456     *  Factory for a {@code MapStream<K,V>}; constructs a stream from an
457     *  instance of
458     *  {@link Map}.
459     *
460     *  @param  <K> The type of the map keys.
461     *  @param  <V> The type of the map values.
462     *  @param  map The map to build the stream from.
463     *  @return A new {@code MapStream<K,V>}.
464     */
465    @API( status = STABLE, since = "0.0.4" )
466    public static <K,V> MapStream<K,V> of( final Map<K,V> map ) { return new DefaultMapStream<>( map.entrySet().stream() ); }
467
468    /**
469     *  Factory for a {@code MapStream<K,V>}; constructs a stream from several
470     *  instances of
471     *  {@link Map}.
472     *
473     *  @param  <K> The type of the map keys.
474     *  @param  <V> The type of the map values.
475     *  @param  maps    The maps to build the stream from.
476     *  @return A new {@code MapStream<K,V>}.
477     */
478    @API( status = STABLE, since = "0.0.4" )
479    @SafeVarargs
480    public static <K,V> MapStream<K,V> ofMaps( final Map<K,V>... maps )
481    {
482        final MapStream<K,V> retValue = new DefaultMapStream<>( Stream.of( maps ).flatMap( map -> map.entrySet().stream() ) );
483
484        //---* Done *----------------------------------------------------------
485        return retValue;
486    }   //  ofMaps()
487
488    /**
489     *  {@inheritDoc}
490     */
491    @Override
492    public MapStream<K,V> onClose( Runnable closeHandler );
493
494    /**
495     *  {@inheritDoc}
496     */
497    @Override
498    public MapStream<K,V> parallel();
499
500    /**
501     *  {@inheritDoc}
502     */
503    @Override
504    public MapStream<K,V> peek( Consumer<? super Entry<K,V>> action );
505
506    /**
507     *  {@inheritDoc}
508     */
509    @Override
510    public MapStream<K,V> sequential();
511
512    /**
513     *  {@inheritDoc}
514     */
515    @Override
516    public MapStream<K,V> skip( long n );
517
518    /**
519     *  {@inheritDoc}
520     */
521    @Override
522    public MapStream<K,V> sorted();
523
524    /**
525     *  {@inheritDoc}
526     */
527    @Override
528    public MapStream<K,V> sorted( Comparator<? super Entry<K,V>> comparator );
529
530    /**
531     *  {@inheritDoc}
532     */
533    @Override
534    public MapStream<K,V> unordered();
535}
536//  interface MapStream
537
538/*
539 *  End of File
540 */