package yokohama.unit.util;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Lists {
    public static <T> List<T> repeat(T obj, int times) {
        @SuppressWarnings("unchecked") T[] array = (T[])new Object[times];
        Arrays.fill(array, obj);
        return Arrays.asList(array);
    }

    public static <T> T last(List<T> list) {
        return list.get(list.size() - 1);
    }

    public static <T> Optional<T> lastOpt(List<T> list) {
        if (list.size() > 0) {
            return Optional.of(Lists.last(list));
        } else {
            return Optional.empty();
        }
    }

    public static <T, U> List<U> mapInitAndLast(
            List<T> list, Function<T, U> initf, Function<T, U> lastf) {
        if (list.isEmpty()) return Collections.emptyList();

        List<T> init = list.subList(0, list.size() - 1);
        T last = last(list);

        return Stream.concat(
                init.stream().map(initf), Stream.of(lastf.apply(last)))
                .collect(Collectors.toList());
    }

    public static <T, U> List<U> flatMapInitAndLast(
            List<T> list,
            Function<T, Stream<U>> initf,
            Function<T, Stream<U>> lastf) {
        if (list.isEmpty()) return Collections.emptyList();

        List<T> init = list.subList(0, list.size() - 1);
        T last = last(list);

        return Stream.concat(init.stream().flatMap(initf), lastf.apply(last))
                .collect(Collectors.toList());
    }
    public static <T, U> List<U> mapFirstAndRest(
            List<T> list, Function<T, U> firstf, Function<T, U> restf) {
        if (list.isEmpty()) return Collections.emptyList();

        T first = list.get(0);
        List<T> rest = list.subList(1, list.size());

        return Stream.concat(
                Stream.of(firstf.apply(first)), rest.stream().map(restf))
                .collect(Collectors.toList());
    }

    public static <T, U> List<U> flatMapFirstAndRest(
            List<T> list,
            Function<T, Stream<U>> firstf,
            Function<T, Stream<U>> restf) {
        if (list.isEmpty()) return Collections.emptyList();

        T first = list.get(0);
        List<T> rest = list.subList(1, list.size());

        return Stream.concat(
                firstf.apply(first), rest.stream().flatMap(restf))
                .collect(Collectors.toList());
    }
}

@@ -787,32 +787,410 @@
     %7D%0D%0A    %7D%0D%0A%0D%0A
+    public static %3CT%3E Pair%3CList%3CT%3E, List%3CT%3E%3E split(List%3CT%3E list, int pos) %7B%0D%0A        List%3CT%3E left = list.subList(0, pos);%0D%0A        List%3CT%3E right = list.subList(pos, list.size());%0D%0A        return new Pair%3C%3E(left, right);%0D%0A    %7D%0D%0A%0D%0A    public static %3CT, U%3E List%3CU%3E map(List%3CT%3E list, Function%3CT, U%3E f) %7B%0D%0A        return list.stream().map(f).collect(Collectors.toList());%0D%0A    %7D%0D%0A%0D%0A
     public stati

Add Lists.split and Lists.map