001/*
002 * Copyright 2023 the original author or authors.
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * https://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package de.cuioss.tools.collect;
017
018import static de.cuioss.tools.collect.MoreCollections.isEmpty;
019
020import java.util.ArrayList;
021import java.util.Arrays;
022import java.util.Collection;
023import java.util.Collections;
024import java.util.HashMap;
025import java.util.HashSet;
026import java.util.Iterator;
027import java.util.List;
028import java.util.Map;
029import java.util.Set;
030import java.util.SortedSet;
031import java.util.TreeSet;
032import java.util.stream.Stream;
033
034import lombok.experimental.UtilityClass;
035
036/**
037 * <h2>Overview</h2> Provides a number of methods simplifying the task of
038 * creating populated {@link java.util.Collection}s. In essence its doing the
039 * same compared to the corresponding com.google.common.collect types but with
040 * different semantics (like naming, types) and is designed as a one-stop
041 * utility class. It differentiates between the subtypes and mutability /
042 * immutability. This class is complementary to the corresponding guava types.
043 * <h3>Lists</h3>
044 *
045 * <pre>
046 *  assertMutable(CollectionLiterals#mutableList("1"));
047 *  assertMutable(CollectionLiterals#mutableList("1", "2"));
048 *  assertMutable(CollectionLiterals#mutableList(Arrays.asList("1", "2").stream()));
049 * </pre>
050 *
051 * <pre>
052 *  assertImmutable(CollectionLiterals#immutableList("1"));
053 *  assertImmutable(CollectionLiterals#immutableList("1", "2"));
054 *  assertImmutable(CollectionLiterals#immutableList(Arrays.asList("1", "2").stream()));
055 * </pre>
056 *
057 * <h3>Sets</h3>
058 *
059 * <pre>
060 *  assertMutable(CollectionLiterals#mutableSet("1"));
061 *  assertMutable(CollectionLiterals#mutableSet("1", "2"));
062 *  assertMutable(CollectionLiterals#mutableSet(Arrays.asList("1", "2").stream()));
063 * </pre>
064 *
065 * <pre>
066 *  assertImmutable(CollectionLiterals#immutableSet("1"));
067 *  assertImmutable(CollectionLiterals#immutableSet("1", "2"));
068 *  assertImmutable(CollectionLiterals#immutableSet(Arrays.asList("1", "2").stream()));
069 * </pre>
070 *
071 * <h3>Maps</h3>
072 *
073 * <pre>
074 * assertMutable(CollectionLiterals#mutableMap());
075 * assertMutable(CollectionLiterals#mutableMap("1", "1-1"));
076 * assertMutable(CollectionLiterals#mutableMap("1", "1-1", "2", "2-2", "3", "3-3", "4", "4-4"));
077 * </pre>
078 *
079 * <pre>
080 * assertImmutable(CollectionLiterals#immutableMap());
081 * assertImmutable(CollectionLiterals#immutableMap("1", "1-1"));
082 * assertImmutable(CollectionLiterals#immutableMap("1", "1-1", "2", "2-2", "3", "3-3", "4", "4-4"));
083 * </pre>
084 *
085 * @author Oliver Wolff
086 */
087@UtilityClass
088public class CollectionLiterals {
089
090    /**
091     * <p>
092     * mutableList.
093     * </p>
094     *
095     * @return a newly created empty {@link java.util.ArrayList}
096     * @param <E> a E class
097     */
098    public static <E> List<E> mutableList() {
099        return new ArrayList<>();
100    }
101
102    /**
103     * Creates a <i>mutable</i> {@code List} instance containing the given elements.
104     *
105     * @param elements to be added
106     * @return the <i>mutable</i> {@link java.util.List} with the given elements
107     * @param <E> a E class
108     */
109    @SafeVarargs
110    public static <E> List<E> mutableList(E... elements) {
111        if (isEmpty(elements)) {
112            return new ArrayList<>();
113        }
114        return new ArrayList<>(Arrays.asList(elements));
115    }
116
117    /**
118     * Creates a <i>mutable</i> {@code List} instance containing the given element
119     *
120     * @param element to be added
121     * @return the <i>mutable</i> {@link java.util.List} with the given element
122     * @param <E> a E class
123     */
124    public static <E> List<E> mutableList(E element) {
125        List<E> list = new ArrayList<>();
126        list.add(element);
127        return list;
128    }
129
130    /**
131     * Creates a <i>mutable</i> {@code List} instance containing the given elements.
132     *
133     * @param elements to be added. If it is null and empty <i>mutable</i> list will
134     *                 be returned
135     * @return the <i>mutable</i> {@link java.util.List} with the given elements
136     * @param <E> a E class
137     */
138    public static <E> List<E> mutableList(Iterable<? extends E> elements) {
139        var list = new ArrayList<E>();
140        if (isEmpty(elements)) {
141            return list;
142        }
143        elements.forEach(list::add);
144        return list;
145    }
146
147    /**
148     * Creates a <i>mutable</i> {@code List} instance containing the given elements.
149     *
150     * @param elements to be added. If it is null and empty <i>mutable</i> list will
151     *                 be returned
152     * @return the <i>mutable</i> {@link java.util.List} with the given elements
153     * @param <E> a E class
154     */
155    public static <E> List<E> mutableList(Collection<? extends E> elements) {
156        if (isEmpty(elements)) {
157            return new ArrayList<>();
158        }
159        return new ArrayList<>(elements);
160    }
161
162    /**
163     * Creates a <i>mutable</i> {@code List} instance containing the given elements.
164     * <em>Caution:</em> The stream will be consumed by this operation
165     *
166     * @param elements to be added. If it is null an empty <i>mutable</i>
167     *                 {@code List} will be returned
168     * @return the <i>mutable</i> {@code List} with the given elements
169     * @param <E> a E class
170     */
171    public static <E> List<E> mutableList(Stream<? extends E> elements) {
172        List<E> list = new ArrayList<>();
173        if (isEmpty(elements)) {
174            return list;
175        }
176        elements.forEach(list::add);
177        return list;
178    }
179
180    /**
181     * Creates a <i>mutable</i> {@code List} instance containing the given elements.
182     *
183     * @param elements to be added. If it is null and empty <i>mutable</i> list will
184     *                 be returned
185     * @return the <i>mutable</i> {@link java.util.List} with the given elements
186     * @param <E> a E class
187     */
188    public static <E> List<E> mutableList(Iterator<? extends E> elements) {
189        List<E> list = new ArrayList<>();
190        if (isEmpty(elements)) {
191            return list;
192        }
193        while (elements.hasNext()) {
194            list.add(elements.next());
195        }
196        return list;
197    }
198
199    /**
200     * Creates an <i>immutable</i> {@code List} instance. Convenience method for
201     * {@link java.util.Collections#emptyList()}
202     *
203     * @return the <i>immutable</i> {@link java.util.List} without any element
204     * @param <E> a E class
205     */
206    public static <E> List<E> immutableList() {
207        return Collections.emptyList();
208    }
209
210    /**
211     * Creates an <i>immutable</i> {@code List} instance containing the given
212     * elements.
213     *
214     * @param elements to be wrapped, must not be null
215     * @return the <i>immutable</i> {@link java.util.List} with the given elements
216     * @param <E> a E class
217     */
218    @SafeVarargs
219    public static <E> List<E> immutableList(E... elements) {
220        if (isEmpty(elements)) {
221            return Collections.emptyList();
222        }
223        return Collections.unmodifiableList(mutableList(elements));
224    }
225
226    /**
227     * Creates an <i>immutable</i> {@code List} instance containing the given
228     * element.
229     *
230     * @param element to be wrapped, must not be null
231     * @return the <i>immutable</i> {@link java.util.List} with the given elements
232     * @param <E> a E class
233     */
234    public static <E> List<E> immutableList(E element) {
235        if (null == element) {
236            return Collections.emptyList();
237        }
238        return Collections.singletonList(element);
239    }
240
241    /**
242     * Creates an <i>immutable</i> {@code List} instance containing the given
243     * elements.
244     *
245     * @param elements to be wrapped, must not be null
246     * @return the <i>immutable</i> {@link java.util.List} with the given elements
247     * @param <E> a E class
248     */
249    public static <E> List<E> immutableList(Iterable<? extends E> elements) {
250        if (isEmpty(elements)) {
251            return Collections.emptyList();
252        }
253        return Collections.unmodifiableList(mutableList(elements));
254    }
255
256    /**
257     * Creates an <i>immutable</i> {@code List} instance containing the given
258     * elements.
259     *
260     * @param elements to be wrapped, must not be null
261     * @return the <i>immutable</i> {@link java.util.List} with the given elements.
262     *         It implicitly creates a copy
263     * @param <E> a E class
264     */
265    public static <E> List<E> immutableList(Collection<? extends E> elements) {
266        if (isEmpty(elements)) {
267            return Collections.emptyList();
268        }
269
270        return Collections.unmodifiableList(mutableList(elements));
271    }
272
273    /**
274     * Creates an <i>immutable</i> {@code List} instance containing the given
275     * elements. <em>Caution:</em> The stream will be consumed by this operation
276     *
277     * @param elements to be wrapped, must not be null
278     * @return the <i>immutable</i> {@link java.util.List} with the given elements
279     * @param <E> a E class
280     */
281    public static <E> List<E> immutableList(Stream<? extends E> elements) {
282        if (isEmpty(elements)) {
283            return Collections.emptyList();
284        }
285        return Collections.unmodifiableList(mutableList(elements));
286    }
287
288    /**
289     * Creates an <i>immutable</i> {@code List} instance containing the given
290     * elements.
291     *
292     * @param elements to be wrapped, must not be null
293     * @return the <i>immutable</i> {@link java.util.List} with the given elements
294     * @param <E> a E class
295     */
296    public static <E> List<E> immutableList(Iterator<? extends E> elements) {
297        if (isEmpty(elements)) {
298            return Collections.emptyList();
299        }
300        return Collections.unmodifiableList(mutableList(elements));
301    }
302
303    /**
304     * <p>
305     * mutableSet.
306     * </p>
307     *
308     * @return a newly created empty {@link java.util.HashSet}
309     * @param <E> a E class
310     */
311    public static <E> Set<E> mutableSet() {
312        return new HashSet<>();
313    }
314
315    /**
316     * <p>
317     * mutableSet.
318     * </p>
319     *
320     * @param element to be added. If it is {@code null} it will not be added
321     * @return a newly created empty {@link java.util.HashSet} with the given
322     *         elements
323     * @param <E> a E class
324     */
325    public static <E> Set<E> mutableSet(E element) {
326        Set<E> set = new HashSet<>();
327        if (null == element) {
328            return set;
329        }
330        set.add(element);
331        return set;
332    }
333
334    /**
335     * <p>
336     * mutableSet.
337     * </p>
338     *
339     * @param elements to be added
340     * @return a newly created empty {@link java.util.HashSet} with the given
341     *         elements
342     * @param <E> a E class
343     */
344    @SafeVarargs
345    public static <E> Set<E> mutableSet(E... elements) {
346        if (isEmpty(elements)) {
347            return new HashSet<>();
348        }
349        return new HashSet<>(Arrays.asList(elements));
350    }
351
352    /**
353     * Creates a <i>mutable</i> {@code Set} instance containing the given elements.
354     *
355     * @param elements to be added. If it is null and empty <i>mutable</i> list will
356     *                 be returned
357     * @return the <i>mutable</i> {@link java.util.Set} with the given elements
358     * @param <E> a E class
359     */
360    public static <E> Set<E> mutableSet(Iterable<? extends E> elements) {
361        Set<E> set = new HashSet<>();
362        if (isEmpty(elements)) {
363            return set;
364        }
365        elements.forEach(set::add);
366        return set;
367
368    }
369
370    /**
371     * Creates a <i>mutable</i> {@code Set} instance containing the given elements.
372     *
373     * @param elements to be added. If it is null and empty <i>mutable</i> list will
374     *                 be returned
375     * @return the <i>mutable</i> {@link java.util.Set} with the given elements
376     * @param <E> a E class
377     */
378    public static <E> Set<E> mutableSet(Collection<? extends E> elements) {
379        if (isEmpty(elements)) {
380            return new HashSet<>();
381        }
382        return new HashSet<>(elements);
383    }
384
385    /**
386     * Creates a <i>mutable</i> {@code Set} instance containing the given elements.
387     *
388     * @param elements to be added. If it is null and empty <i>mutable</i> list will
389     *                 be returned
390     * @return the <i>mutable</i> {@link java.util.Set} with the given elements
391     * @param <E> a E class
392     */
393    public static <E> Set<E> mutableSet(Iterator<? extends E> elements) {
394        Set<E> set = new HashSet<>();
395        if (isEmpty(elements)) {
396            return set;
397        }
398        while (elements.hasNext()) {
399            set.add(elements.next());
400        }
401        return set;
402    }
403
404    /**
405     * Creates a <i>mutable</i> {@code Set} instance containing the given elements.
406     * <em>Caution:</em> The stream will be consumed by this operation
407     *
408     * @param elements to be added. If it is null and empty <i>mutable</i>
409     *                 {@link java.util.Set} will be returned
410     * @return the <i>mutable</i> {@link java.util.Set} with the given elements
411     * @param <E> a E class
412     */
413    public static <E> Set<E> mutableSet(Stream<? extends E> elements) {
414        Set<E> set = new HashSet<>();
415        if (isEmpty(elements)) {
416            return set;
417        }
418        elements.forEach(set::add);
419        return set;
420    }
421
422    /**
423     * <p>
424     * immutableSet.
425     * </p>
426     *
427     * @return a newly created empty {@link java.util.HashSet} Convenience method
428     *         for {@link java.util.Collections#emptySet()}
429     * @param <E> a E class
430     */
431    public static <E> Set<E> immutableSet() {
432        return Collections.emptySet();
433    }
434
435    /**
436     * Creates an <i>immutable</i> {@code Set} instance containing the given
437     * elements.
438     *
439     * @param element to be wrapped, must not be null
440     * @return the <i>immutable</i> {@link java.util.Set} with the given elements
441     * @param <E> a E class
442     */
443    public static <E> Set<E> immutableSet(E element) {
444        if (null == element) {
445            return Collections.emptySet();
446        }
447        return Collections.singleton(element);
448    }
449
450    /**
451     * Creates an <i>immutable</i> {@code Set} instance containing the given
452     * elements.
453     *
454     * @param elements to be wrapped, must not be null
455     * @return the <i>immutable</i> {@link java.util.Set} with the given elements
456     * @param <E> a E class
457     */
458    @SafeVarargs
459    public static <E> Set<E> immutableSet(E... elements) {
460        if (isEmpty(elements)) {
461            return Collections.emptySet();
462        }
463        return Collections.unmodifiableSet(mutableSet(elements));
464    }
465
466    /**
467     * Creates an <i>immutable</i> {@code Set} instance containing the given
468     * elements.
469     *
470     * @param elements to be wrapped
471     * @return the <i>immutable</i> {@link java.util.Set} with the given elements
472     * @param <E> a E class
473     */
474    public static <E> Set<E> immutableSet(Iterable<? extends E> elements) {
475        if (isEmpty(elements)) {
476            return Collections.emptySet();
477        }
478        return Collections.unmodifiableSet(mutableSet(elements));
479    }
480
481    /**
482     * Creates an <i>immutable</i> {@code Set} instance containing the given
483     * elements.
484     *
485     * @param elements to be wrapped, must not be null
486     * @return the <i>immutable</i> {@link java.util.Set} with the given elements
487     * @param <E> a E class
488     */
489    public static <E> Set<E> immutableSet(Iterator<? extends E> elements) {
490        if (isEmpty(elements)) {
491            return Collections.emptySet();
492        }
493        return Collections.unmodifiableSet(mutableSet(elements));
494    }
495
496    /**
497     * Creates an <i>immutable</i> {@code Set} instance containing the given
498     * elements. <em>Caution:</em> The stream will be consumed by this operation
499     *
500     * @param elements to be wrapped, must not be null
501     * @return the <i>immutable</i> {@link java.util.Set} with the given elements
502     * @param <E> a E class
503     */
504    public static <E> Set<E> immutableSet(Stream<? extends E> elements) {
505        if (isEmpty(elements)) {
506            return Collections.emptySet();
507        }
508        return Collections.unmodifiableSet(mutableSet(elements));
509    }
510
511    /**
512     * <p>
513     * mutableSortedSet.
514     * </p>
515     *
516     * @return a newly created empty {@link java.util.TreeSet}
517     * @param <E> a E class
518     */
519    public static <E> SortedSet<E> mutableSortedSet() {
520        return new TreeSet<>();
521    }
522
523    /**
524     * <p>
525     * mutableSortedSet.
526     * </p>
527     *
528     * @param element to be added. If it is {@code null} an empty
529     *                {@link java.util.SortedSet} will be returned
530     * @return a newly created empty {@link java.util.TreeSet} with the given
531     *         element
532     * @param <E> a E class
533     */
534    public static <E> SortedSet<E> mutableSortedSet(E element) {
535        SortedSet<E> set = new TreeSet<>();
536        if (null == element) {
537            return set;
538        }
539        set.add(element);
540        return set;
541    }
542
543    /**
544     * <p>
545     * mutableSortedSet.
546     * </p>
547     *
548     * @param elements to be added
549     * @return a newly created empty {@link java.util.TreeSet} with the given
550     *         elements
551     * @param <E> a E class
552     */
553    @SafeVarargs
554    public static <E> SortedSet<E> mutableSortedSet(E... elements) {
555        SortedSet<E> set = new TreeSet<>();
556        if (isEmpty(elements)) {
557            return set;
558        }
559        set.addAll(Arrays.asList(elements));
560        return set;
561    }
562
563    /**
564     * Creates a <i>mutable</i> {@code SortedSet} instance containing the given
565     * elements.
566     *
567     * @param elements to be added. If it is null and empty <i>mutable</i> list will
568     *                 be returned
569     * @return the <i>mutable</i> {@link java.util.TreeSet} with the given elements
570     * @param <E> a E class
571     */
572    public static <E> SortedSet<E> mutableSortedSet(Iterable<? extends E> elements) {
573        SortedSet<E> set = new TreeSet<>();
574        if (null == elements) {
575            return set;
576        }
577        elements.forEach(set::add);
578        return set;
579    }
580
581    /**
582     * Creates a <i>mutable</i> {@code SortedSet} instance containing the given
583     * elements.
584     *
585     * @param elements to be added. If it is null and empty <i>mutable</i> list will
586     *                 be returned
587     * @return the <i>mutable</i> {@link java.util.Set} with the given elements
588     * @param <E> a E class
589     */
590    public static <E> SortedSet<E> mutableSortedSet(Iterator<? extends E> elements) {
591        SortedSet<E> set = new TreeSet<>();
592        if (null == elements) {
593            return set;
594        }
595        while (elements.hasNext()) {
596            set.add(elements.next());
597        }
598        return set;
599    }
600
601    /**
602     * Creates a <i>mutable</i> {@code SortedSet} instance containing the given
603     * elements. <em>Caution:</em> The stream will be consumed by this operation
604     *
605     * @param elements to be added. If it is null and empty <i>mutable</i> list will
606     *                 be returned
607     * @return the <i>mutable</i> {@link java.util.Set} with the given elements
608     * @param <E> a E class
609     */
610    public static <E> SortedSet<E> mutableSortedSet(Stream<? extends E> elements) {
611        SortedSet<E> set = new TreeSet<>();
612        if (null == elements) {
613            return set;
614        }
615        elements.forEach(set::add);
616        return set;
617    }
618
619    /**
620     * <p>
621     * immutableSortedSet.
622     * </p>
623     *
624     * @return a newly created empty {@link java.util.SortedSet} Convenience method
625     *         for {@link java.util.Collections#emptySortedSet()}
626     * @param <E> a E class
627     */
628    public static <E> SortedSet<E> immutableSortedSet() {
629        return Collections.emptySortedSet();
630    }
631
632    /**
633     * Creates an <i>immutable</i> {@code SortedSet} instance containing the given
634     * elements.
635     *
636     * @param element to be wrapped, must not be null
637     * @return the <i>immutable</i> {@link java.util.Set} with the given elements
638     * @param <E> a E class
639     */
640    public static <E> SortedSet<E> immutableSortedSet(E element) {
641        if (null == element) {
642            return Collections.emptySortedSet();
643        }
644        return Collections.unmodifiableSortedSet(mutableSortedSet(element));
645    }
646
647    /**
648     * Creates an <i>immutable</i> {@code SortedSet} instance containing the given
649     * elements.
650     *
651     * @param elements to be wrapped, must not be null
652     * @return the <i>immutable</i> {@link java.util.Set} with the given elements
653     * @param <E> a E class
654     */
655    @SafeVarargs
656    public static <E> SortedSet<E> immutableSortedSet(E... elements) {
657        return Collections.unmodifiableSortedSet(mutableSortedSet(elements));
658    }
659
660    /**
661     * Creates an <i>immutable</i> {@code SortedSet} instance containing the given
662     * elements.
663     *
664     * @param elements to be wrapped, must not be null
665     * @return the <i>immutable</i> {@link java.util.Set} with the given elements
666     * @param <E> a E class
667     */
668    public static <E> SortedSet<E> immutableSortedSet(Iterable<? extends E> elements) {
669        return Collections.unmodifiableSortedSet(mutableSortedSet(elements));
670    }
671
672    /**
673     * Creates an <i>immutable</i> {@code SortedSet} instance containing the given
674     * elements.
675     *
676     * @param elements to be wrapped, must not be null
677     * @return the <i>immutable</i> {@link java.util.Set} with the given elements
678     * @param <E> a E class
679     */
680    public static <E> SortedSet<E> immutableSortedSet(Iterator<? extends E> elements) {
681        return Collections.unmodifiableSortedSet(mutableSortedSet(elements));
682    }
683
684    /**
685     * Creates an <i>immutable</i> {@code SortedSet} instance containing the given
686     * elements. <em>Caution:</em> The stream will be consumed by this operation
687     *
688     * @param elements to be wrapped, must not be null
689     * @return the <i>immutable</i> {@link java.util.Set} with the given elements
690     * @param <E> a E class
691     */
692    public static <E> SortedSet<E> immutableSortedSet(Stream<? extends E> elements) {
693        return Collections.unmodifiableSortedSet(mutableSortedSet(elements));
694    }
695
696    /**
697     * <p>
698     * mutableMap.
699     * </p>
700     *
701     * @return an empty <i>mutable</i> Map
702     * @param <K> a K class
703     * @param <V> a V class
704     */
705    public static <K, V> Map<K, V> mutableMap() {
706        return new HashMap<>();
707    }
708
709    /**
710     * Convenience method for the inline creation of a map with values
711     *
712     * @param k key to be added
713     * @param v value to be added
714     * @return a <i>mutable</i> Map with the given elements
715     * @param <K> a K class
716     * @param <V> a V class
717     */
718    public static <K, V> Map<K, V> mutableMap(K k, V v) {
719        Map<K, V> map = new HashMap<>();
720        map.put(k, v);
721        return map;
722    }
723
724    /**
725     * Convenience method for the inline creation of a map with values
726     *
727     * @param k1 key to be added
728     * @param v1 value to be added
729     * @param k2 key to be added
730     * @param v2 value to be added
731     * @return a <i>mutable</i> Map with the given elements
732     * @param <K> a K class
733     * @param <V> a V class
734     */
735    public static <K, V> Map<K, V> mutableMap(K k1, V v1, K k2, V v2) {
736        Map<K, V> map = new HashMap<>();
737        map.put(k1, v1);
738        map.put(k2, v2);
739        return map;
740    }
741
742    /**
743     * Convenience method for the inline creation of a map with values
744     *
745     * @param k1 key to be added
746     * @param v1 value to be added
747     * @param k2 key to be added
748     * @param v2 value to be added
749     * @param k3 key to be added
750     * @param v3 value to be added
751     * @return a <i>mutable</i> Map with the given elements
752     * @param <K> a K class
753     * @param <V> a V class
754     */
755    public static <K, V> Map<K, V> mutableMap(K k1, V v1, K k2, V v2, K k3, V v3) {
756        Map<K, V> map = new HashMap<>();
757        map.put(k1, v1);
758        map.put(k2, v2);
759        map.put(k3, v3);
760        return map;
761    }
762
763    /**
764     * Convenience method for the inline creation of a map with values
765     *
766     * @param k1 key to be added
767     * @param v1 value to be added
768     * @param k2 key to be added
769     * @param v2 value to be added
770     * @param k3 key to be added
771     * @param v3 value to be added
772     * @param k4 key to be added
773     * @param v4 value to be added
774     * @return a <i>mutable</i> Map with the given elements
775     * @param <K> a K class
776     * @param <V> a V class
777     */
778    @SuppressWarnings("squid:S00107") // owolff: Number of parameters match to the use-case
779    public static <K, V> Map<K, V> mutableMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
780        Map<K, V> map = new HashMap<>();
781        map.put(k1, v1);
782        map.put(k2, v2);
783        map.put(k3, v3);
784        map.put(k4, v4);
785        return map;
786    }
787
788    /**
789     * <p>
790     * immutableMap.
791     * </p>
792     *
793     * @return an empty <i>mutable</i> Map
794     * @param <K> a K class
795     * @param <V> a V class
796     */
797    public static <K, V> Map<K, V> immutableMap() {
798        return Collections.emptyMap();
799    }
800
801    /**
802     * Shorthand to {@link java.util.Collections#unmodifiableMap(Map)}
803     *
804     * @param source a {@link java.util.Map} object
805     * @return an <i>immutable</i> Map with the given elements
806     * @param <K> a K class
807     * @param <V> a V class
808     */
809    public static <K, V> Map<K, V> immutableMap(Map<K, V> source) {
810        return Collections.unmodifiableMap(source);
811    }
812
813    /**
814     * Copies the entries of the given map stream into a new map which is then
815     * returned as an unmodifiable map.
816     *
817     * @param elements to be copied
818     * @param <K>      key type
819     * @param <V>      value type
820     * @return unmodifiable map with entries form the given stream
821     */
822    public static <K, V> Map<K, V> immutableMap(Stream<Map.Entry<K, V>> elements) {
823        final Map<K, V> map = mutableMap();
824        elements.forEach(entry -> map.put(entry.getKey(), entry.getValue()));
825        return Collections.unmodifiableMap(map);
826    }
827
828    /**
829     * Convenience method for the inline creation of a map with values
830     *
831     * @param k key to be added
832     * @param v value to be added
833     * @return an <i>immutable</i> Map with the given elements
834     * @param <K> a K class
835     * @param <V> a V class
836     */
837    public static <K, V> Map<K, V> immutableMap(K k, V v) {
838        Map<K, V> map = mutableMap();
839        map.put(k, v);
840        return Collections.unmodifiableMap(map);
841    }
842
843    /**
844     * Convenience method for the inline creation of a map with values
845     *
846     * @param k1 key to be added
847     * @param v1 value to be added
848     * @param k2 key to be added
849     * @param v2 value to be added
850     * @return an <i>immutable</i> Map with the given elements
851     * @param <K> a K class
852     * @param <V> a V class
853     */
854    public static <K, V> Map<K, V> immutableMap(K k1, V v1, K k2, V v2) {
855        Map<K, V> map = mutableMap();
856        map.put(k1, v1);
857        map.put(k2, v2);
858        return Collections.unmodifiableMap(map);
859    }
860
861    /**
862     * Convenience method for the inline creation of a map with values
863     *
864     * @param k1 key to be added
865     * @param v1 value to be added
866     * @param k2 key to be added
867     * @param v2 value to be added
868     * @param k3 key to be added
869     * @param v3 value to be added
870     * @return an <i>immutable</i> Map with the given elements
871     * @param <K> a K class
872     * @param <V> a V class
873     */
874    public static <K, V> Map<K, V> immutableMap(K k1, V v1, K k2, V v2, K k3, V v3) {
875        Map<K, V> map = mutableMap();
876        map.put(k1, v1);
877        map.put(k2, v2);
878        map.put(k3, v3);
879        return Collections.unmodifiableMap(map);
880    }
881
882    /**
883     * Convenience method for the inline creation of a map with values
884     *
885     * @param k1 key to be added
886     * @param v1 value to be added
887     * @param k2 key to be added
888     * @param v2 value to be added
889     * @param k3 key to be added
890     * @param v3 value to be added
891     * @param k4 key to be added
892     * @param v4 value to be added
893     * @return an <i>immutable</i> Map with the given elements
894     * @param <K> a K class
895     * @param <V> a V class
896     */
897    @SuppressWarnings("squid:S00107") // owolff: Number of parameters match to the use-case
898    public static <K, V> Map<K, V> immutableMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
899        Map<K, V> map = mutableMap();
900        map.put(k1, v1);
901        map.put(k2, v2);
902        map.put(k3, v3);
903        map.put(k4, v4);
904        return Collections.unmodifiableMap(map);
905    }
906
907}