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> Pair<List<T>, List<T>> split(List<T> list, int pos) {
        List<T> left = list.subList(0, pos);
        List<T> right = list.subList(pos, list.size());
        return new Pair<>(left, right);
    }

    public static <T, U> List<U> map(List<T> list, Function<T, U> f) {
        return list.stream().map(f).collect(Collectors.toList());
    }

    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());
    }
}

@@ -98,20 +98,70 @@
 va.util.
-List
+HashMap;%0D%0Aimport java.util.List;%0D%0Aimport java.util.Map
 ;%0D%0Aimpor
@@ -3030,12 +3030,426 @@
 %0D%0A    %7D%0D
+%0A%0D%0A    public static %3CT, U, V%3E Map%3CU, V%3E listToMap(%0D%0A            List%3CT%3E list, Function%3CT, Pair%3CU, V%3E%3E f) %7B%0D%0A        return list.stream().collect(%0D%0A                () -%3E new HashMap%3C%3E(),%0D%0A                (map, e) -%3E %7B%0D%0A                    Pair%3CU, V%3E pair = f.apply(e);%0D%0A                    map.put(pair.getFirst(), pair.getSecond());%0D%0A                %7D,%0D%0A                (map1, map2) -%3E map1.putAll(map2));%0D%0A    %7D%0D
 %0A%7D%0D%0A

Add listToMap method