All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.abego.commons.seq.SeqUtil Maven / Gradle / Ivy

There is a newer version: 1.1.0
Show newest version
/*
 * MIT License
 *
 * Copyright (c) 2020 Udo Borkowski, ([email protected])
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package org.abego.commons.seq;

import org.abego.commons.lang.exception.MustNotInstantiateException;
import org.abego.commons.util.ListUtil;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.abego.commons.lang.IterableUtil.isEmpty;
import static org.abego.commons.seq.MappedSeq.newMappedSeq;
import static org.abego.commons.seq.SeqForArray.newSeqForArray;
import static org.abego.commons.seq.SeqForIterable.newSeqForIterable;
import static org.abego.commons.seq.SeqForList.newSeqForList;
import static org.abego.commons.seq.SeqNonEmptyUtil.newSeqNonEmpty;
import static org.abego.commons.util.ListUtil.sortedList;

@SuppressWarnings("WeakerAccess")
public final class SeqUtil {
    SeqUtil() {
        throw new MustNotInstantiateException();
    }

    /**
     * Return an (/the) empty Seq, i.e. a Seq with no items.
     */
    public static  Seq emptySeq() {
        return SeqHelper.emptySeq();
    }

    /**
     * Return true if both {@link Seq}s (seq and other)
     * are equal, false otherwise.
     *
     * 

The implementation does not use {@link Seq#equals(Object)} but * handles the {@link Seq}s as * {@link Iterable}s. Therefore this method is typically used in the * {@link Seq#equals(Object)} code of concrete Seq implementations, like here: *

     * public boolean equals(Object o) {
     *     if (!(o instanceof Seq)) return false;
     *
     *     return SeqUtil.seqsAreEqual(this, (Seq<?>) o);
     * }
     * 
* Typically a corresponding {@link Seq#hashCode()} implementation then uses * {@link org.abego.commons.lang.IterableUtil#hashCodeForIterable(Iterable)} * like here: * *
     * public int hashCode() {
     *     return hashCodeForIterable(this);
     * }
     * 
*/ public static boolean seqsAreEqual(Seq seq, Seq other) { return SeqHelper.seqsAreEqual(seq, other); } /** * Return a {@link Seq} with the given items. * *

Instead of multiple individual items you may also pass an array of type * T[] with items. */ @SafeVarargs public static Seq newSeq(T... items) { return items.length == 0 ? SeqHelper.emptySeq() : newSeqForArray(items); } /** * Return a {@link Seq} with the items of the given list. * *

The list must not change after the Seq is created.

*/ public static Seq newSeq(List list) { return list.isEmpty() ? SeqHelper.emptySeq() : newSeqForList(list); } /** * Return a {@link Seq} for the given iterable. * *

The Iterable must not change after the Seq is created.

*/ public static Seq newSeq(Iterable iterable) { return isEmpty(iterable) ? SeqHelper.emptySeq() : newSeqForIterable(iterable); } @SuppressWarnings("unchecked") public static Seq newSeq(Stream stream) { return SeqUtil.newSeq((T @NonNull []) stream.toArray()); } /** * Return a {@link Seq} with the given item or an empty Seq * if the item is {@code null}. */ public static Seq newSeqOfNullable(@Nullable T item) { return item == null ? SeqUtil.emptySeq() : newSeq(item); } /** * Return a new {@link Seq} consisting of the items of seq that match * the predicate. */ public static Seq filter(Seq seq, Predicate condition) { return newSeq(seq.stream().filter(condition).collect(Collectors.toList())); } /** * Return a new {@link Seq} consisting of the results of applying the given * mapper function to the elements of the seq. */ public static Seq map(Seq seq, Function mapper) { return newMappedSeq(seq, mapper); } /** * Return a new {@link Seq} consisting of the elements of iterable * sorted by the given sortKey. */ public static > Seq sortedBy( Iterable iterable, Function sortKey) { return newSeq(ListUtil.toSortedList(iterable, Comparator.comparing(sortKey))); } /** * Return a new {@link Seq} consisting of the elements of iterable, * sorted in ascending order, according to the {@linkplain Comparable * natural ordering} of its elements. * *

All elements in the iterable must implement the {@link Comparable} * interface. Furthermore, all elements in the iterable must be * mutually comparable (that is, {@code e1.compareTo(e2)} * must not throw a {@code ClassCastException} for any elements * {@code e1} and {@code e2} in the iterable). */ public static Seq sorted(Iterable iterable) { List list = ListUtil.toList(iterable); list.sort(null); return newSeq(list); } /** * Return a new {@link Seq} consisting of the elements of iterable, * sorted in ascending order, according to the given comparator. * *

All elements in the iterable must be mutually comparable using the * specified comparator (that is, {@code c.compare(e1, e2)} must not throw * a {@code ClassCastException} for any elements {@code e1} and {@code e2} * in the iterable). */ public static Seq sorted(Iterable iterable, Comparator comparator) { List list = ListUtil.toList(iterable); list.sort(comparator); return newSeq(list); } /** * Return the items of the iterable in groups of equal items, with the equality defined by the * comparator. */ public static Seq> groupedBy(Iterable iterable, Comparator comparator) { List> result = new ArrayList<>(); @Nullable List currentGroup = null; for (T item : sortedList(iterable, comparator)) { if (currentGroup == null) { currentGroup = ListUtil.list(item); } else if (comparator.compare(currentGroup.get(0), item) == 0) { currentGroup.add(item); } else { result.add(newSeqNonEmpty(currentGroup)); currentGroup = ListUtil.list(item); } } if (currentGroup != null) { result.add(newSeqNonEmpty(currentGroup)); } return SeqUtil.newSeq(result); } /** * Returns a sequence of objects of type R, with each object * representing the result of merging groups of items of the * iterable according to the mergeFunction and * the groups defined by the comparator. * *

In detail: *

    *
  • Group the items of the iterable by the * comparator, i.e. items that are "equal" according to * the comparator are in the same group.
  • *
  • Merge the items of each group to a single object of type * R using the mergeFunction.
  • *
  • Return the sequence of all merged objects, in the order defined * by the comparator
  • *
*/ public static Seq groupedAndMerged( Iterable iterable, Comparator comparator, Function, R> mergeFunction) { return groupedBy(iterable, comparator).map(mergeFunction); } public static Seq reverse(Seq seq) { List result = new ArrayList<>(); for (int i = seq.size() - 1; i >= 0; i--) { result.add(seq.item(i)); } return newSeq(result); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy