CollectionUtil:一个函数式风格的集合工具

  • Post author:
  • Post category:其他




CollectionUtil:一个函数式风格的集合工具

本文分享一个函数式风格的集合操作工具。



使用示例

List<Integer> list = Arrays.asList(1, 2, 3, 4);
int size = CollectionUtil.size(list);//=> 4
boolean empty = CollectionUtil.isEmpty(list);//=> false
boolean notEmpty = CollectionUtil.isNotEmpty(list);//=> true

boolean indexValid = CollectionUtil.isIndexValid(list, 3);//=> true
boolean indexValid1 = CollectionUtil.isIndexValid(list, 4);//=> false

List<Object> list1 = CollectionUtil.list();//=> empty list
List<Integer> list2 = CollectionUtil.list(1);//=> (1)
List<Integer> list3 = CollectionUtil.list(list);//=> (1,2,3,4)
List<Integer> list4 = CollectionUtil.list(1, 2, 3, 4);//=> (1,2,3,4)
List<Integer> list5 = CollectionUtil.ensure(list);//=> list
List<Integer> list6 = CollectionUtil.ensure((List<Integer>) null);//=> empty list
Map<String, Integer> map = CollectionUtil.ensure(Collections.singletonMap("one", 1));//=> map contains: one - 1
Map<String, Integer> map1 = CollectionUtil.ensure((Map<String, Integer>) null);//=> empty map
Set<Integer> set = CollectionUtil.ensure(new HashSet<>(list));//=> set contains: 1,2,3,4
Set<Integer> set1 = CollectionUtil.ensure((Set<Integer>) null);//=> empty set

List<Integer> copyList = CollectionUtil.copy(list);//=> (1,2,3,4)

Integer head = CollectionUtil.head(list);//=> 1
List<Integer> tailList = CollectionUtil.tail(list);//=> (2,3,4)
List<Integer> list7 = CollectionUtil.append(list, 0);//=> (1,2,3,4,0)

CollectionUtil.forEach(list, i -> System.out.println("int:" + i));
List<Integer> reversedList = CollectionUtil.reverse(list);//=> (4,3,2,1)
List<Integer> rangeList = CollectionUtil.range(1, 5);//=> (1,2,3,4)
Integer integer1 = CollectionUtil.find(list, i -> i % 2 == 0, -1);//=> 2
Integer integer2 = CollectionUtil.find(list, i -> i > 10, -1);//=> -1
int count = CollectionUtil.count(list, i -> i % 2 == 0);//=> 2
boolean contains = CollectionUtil.contains(list, i -> i % 2 == 0);//=> true
List<Integer> concatList = CollectionUtil.concat(list,
        Arrays.asList(11, 22),
        Arrays.asList(33, 44));//=> (1,2,3,4,11,22,33,44)
CollectionUtil.doTimes(3, i -> {
    System.out.print("(" + i + ")");
});//打印 (0) (1) (2)
List<Integer> list8 = CollectionUtil.doTimes(5, i -> {
    return i * i;
});//=> (0,1,4,9,16)

List<Integer> filteredList = CollectionUtil.filter(list, i -> i % 2 == 0);//=> (2,4)
String reducedStr = CollectionUtil
        .reduce(list, new StringBuilder(),
                (builder, integer) -> builder.append('(').append(integer).append(')'))
        .toString();//=> "(1)(2)(3)(4)"
List<Integer> list9 = CollectionUtil.map(list, i -> i * 10);//=> (10,20,30,40)
List<String> list10 = CollectionUtil.map(
        Arrays.asList(1, 2, 3, 4),
        Arrays.asList("one", "two", "three", "four"),
        i -> s -> s + ":" + i);//=> ("one:1","two:2","three:3","four:4")



完整实现

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * 函数式集合工具类
 *
 * @author LeZheng
 */
public class CollectionUtil {

    /**
     * 获取集合的大小
     *
     * @param collection
     * @return 集合的大小或0(集合为空时)
     */
    public static int size(@Nullable Collection<?> collection) {
        return collection == null ? 0 : collection.size();
    }

    /**
     * 判断集合是否为空
     *
     * @param collection
     * @return true:null或空集合;否则为false
     */
    public static boolean isEmpty(@Nullable Collection<?> collection) {
        return collection == null || collection.isEmpty();
    }

    /**
     * isEmpty的取反,判断集合是否不为空
     *
     * @param collection
     * @return
     */
    public static boolean isNotEmpty(@Nullable Collection<?> collection) {
        return !isEmpty(collection);
    }

    /**
     * 判断索引是否合法
     *
     * @param collection 目标集合
     * @param index      目标索引
     * @return 如果合法返回true,否则返回false
     */
    public static boolean isIndexValid(@Nullable Collection<?> collection, int index) {
        return collection != null && index >= 0 && index < collection.size();
    }

    /* 构建空的不可变集合 */
    public static <T> List<T> list() {
        return Collections.emptyList();
    }

    /* 构建单元素的不可变集合 */
    public static <T> List<T> list(T t) {
        return Collections.singletonList(t);
    }

    /* 构建一个列表的不可变副本 */
    public static <T> List<T> list(List<T> list) {
        return Collections.unmodifiableList(new ArrayList<>(list));
    }

    /* 根据可变参数构建不可变副本 */
    public static <T> List<T> list(T... t) {
        return Collections.unmodifiableList(Arrays.asList(Arrays.copyOf(t, t.length)));
    }

    /**
     * 复制一个列表
     *
     * @param list
     * @return list的一个可变列表副本
     */
    public static <T> List<T> copy(List<T> list) {
        return new ArrayList<>(list);
    }

    /**
     * 获取列表的头元素
     *
     * @param list
     * @return 列表第一个元素,如果列表为空则抛出异常
     */
    public static <T> T head(List<T> list) {
        if (isEmpty(list)) {
            throw new IllegalStateException("head of empty list");
        }
        return list.get(0);
    }

    /**
     * 列表的尾部元素(除了第一个以外的元素集合)
     *
     * @param list
     * @return 列表中除了第一个元素以外的剩余部分,列表为空则抛出异常
     */
    public static <T> List<T> tail(List<T> list) {
        if (isEmpty(list)) {
            throw new IllegalStateException("tail of empty list");
        }
        List<T> ts = copy(list);
        ts.remove(0);
        return Collections.unmodifiableList(ts);
    }

    /* 非破坏性地往列表追加元素,得到一个一个新列表 */
    public static <T> List<T> append(List<T> list, T t) {
        List<T> ts = copy(list);
        ts.add(t);
        return Collections.unmodifiableList(ts);
    }

    /* 对列表执行 foreach 操作 */
    public static <T> Collection<T> forEach(Collection<T> list, Consumer<? super T> consumer) {
        return foldLeft(list, list, l -> t -> {
            consumer.accept(t);
            return l;
        });
    }

    public static <T, U> List<U> map(Collection<T> collection, Function<T, U> function) {
        return foldLeft(collection, new ArrayList<>(collection.size()), l -> t -> {
            l.add(function.apply(t));
            return l;
        });
    }

    public static <T, T2, U> List<U> map(Collection<T> c1, Collection<T2> c2, Function<T, Function<T2, U>> function) {
        return foldLeft(c1, c2, new ArrayList<>(c1.size()), l -> t1 -> t2 -> {
            l.add(function.apply(t1).apply(t2));
            return l;
        });
    }

    public static <T, T2, T3, U> List<U> map(Collection<T> c1, Collection<T2> c2, Collection<T3> c3,
                                             Function<T, Function<T2, Function<T3, U>>> function) {
        return foldLeft(c1, c2, c3, new ArrayList<>(c1.size()), l -> t1 -> t2 -> t3 -> {
            l.add(function.apply(t1).apply(t2).apply(t3));
            return l;
        });
    }

    public static <T, T2, T3, T4, U> List<U> map(Collection<T> c1, Collection<T2> c2, Collection<T3> c3, Collection<T4> c4,
                                                 Function<T, Function<T2, Function<T3, Function<T4, U>>>> function) {
        return foldLeft(c1, c2, c3, c4, new ArrayList<>(c1.size()), l -> t1 -> t2 -> t3 -> t4 -> {
            l.add(function.apply(t1).apply(t2).apply(t3).apply(t4));
            return l;
        });
    }

    public static <T, T2, T3, T4, T5, U> List<U> map(Collection<T> c1, Collection<T2> c2, Collection<T3> c3, Collection<T4> c4, Collection<T5> c5,
                                                     Function<T, Function<T2, Function<T3, Function<T4, Function<T5, U>>>>> function) {
        return foldLeft(c1, c2, c3, c4, c5, new ArrayList<>(c1.size()), l -> t1 -> t2 -> t3 -> t4 -> t5 -> {
            l.add(function.apply(t1).apply(t2).apply(t3).apply(t4).apply(t5));
            return l;
        });
    }

    public static <T, U> U foldLeft(Collection<T> c, U identity, Function<U, Function<T, U>> function) {
        U result = identity;
        Iterator<T> iterator1 = c.iterator();
        while (iterator1.hasNext()) {
            result = function.apply(result).apply(iterator1.next());
        }
        return result;
    }

    public static <T, T2, U> U foldLeft(Collection<T> c, Collection<T2> c2, U identity, Function<U, Function<T, Function<T2, U>>> function) {
        U result = identity;
        Iterator<T> iterator1 = c.iterator();
        Iterator<T2> iterator2 = c2.iterator();
        while (iterator1.hasNext() && iterator2.hasNext()) {
            result = function.apply(result).apply(iterator1.next()).apply(iterator2.next());
        }
        return result;
    }

    public static <T, T2, T3, U> U foldLeft(Collection<T> c, Collection<T2> c2, Collection<T3> c3, U identity,
                                            Function<U, Function<T, Function<T2, Function<T3, U>>>> function) {
        U result = identity;
        Iterator<T> iterator1 = c.iterator();
        Iterator<T2> iterator2 = c2.iterator();
        Iterator<T3> iterator3 = c3.iterator();
        while (iterator1.hasNext() && iterator2.hasNext() && iterator3.hasNext()) {
            result = function.apply(result).apply(iterator1.next()).apply(iterator2.next()).apply(iterator3.next());
        }
        return result;
    }

    public static <T, T2, T3, T4, U> U foldLeft(Collection<T> c, Collection<T2> c2, Collection<T3> c3, Collection<T4> c4, U identity,
                                                Function<U, Function<T, Function<T2, Function<T3, Function<T4, U>>>>> function) {
        U result = identity;
        Iterator<T> iterator1 = c.iterator();
        Iterator<T2> iterator2 = c2.iterator();
        Iterator<T3> iterator3 = c3.iterator();
        Iterator<T4> iterator4 = c4.iterator();
        while (iterator1.hasNext() && iterator2.hasNext() && iterator3.hasNext() && iterator4.hasNext()) {
            result = function.apply(result).apply(iterator1.next()).apply(iterator2.next()).apply(iterator3.next()).apply(iterator4.next());
        }
        return result;
    }

    public static <T, T2, T3, T4, T5, U> U foldLeft(Collection<T> c, Collection<T2> c2, Collection<T3> c3, Collection<T4> c4, Collection<T5> c5, U identity,
                                                    Function<U, Function<T, Function<T2, Function<T3, Function<T4, Function<T5, U>>>>>> function) {
        U result = identity;
        Iterator<T> iterator1 = c.iterator();
        Iterator<T2> iterator2 = c2.iterator();
        Iterator<T3> iterator3 = c3.iterator();
        Iterator<T4> iterator4 = c4.iterator();
        Iterator<T5> iterator5 = c5.iterator();
        while (iterator1.hasNext() && iterator2.hasNext() && iterator3.hasNext() && iterator4.hasNext() && iterator5.hasNext()) {
            result = function.apply(result).apply(iterator1.next()).apply(iterator2.next()).apply(iterator3.next()).apply(iterator4.next()).apply(iterator5.next());
        }
        return result;
    }

    public static <T, U> U foldRight(List<T> list, U identity, Function<T, Function<U, U>> function) {
        U result = identity;
        ListIterator<T> iterator = list.listIterator(list.size());
        while (iterator.hasPrevious()) {
            T t = iterator.previous();
            result = function.apply(t).apply(result);
        }
        return result;
    }

    /* 非破坏性地倒转元素 */
    public static <T> List<T> reverse(@NonNull List<T> list) {
        return foldRight(list, new ArrayList<>(list.size()), (T a) -> (List<T> b) -> {
            b.add(a);
            return b;
        });
    }

    public static <T> List<T> unfold(T seed, Function<T, T> f, Predicate<T> p) {
        List<T> result = new LinkedList<>();
        T temp = seed;
        while (p.test(temp)) {
            result.add(temp);
            temp = f.apply(temp);
        }
        return new ArrayList<>(result);
    }

    /**
     * 得到指定范围的整数列表
     *
     * @param start 开始大小(包含)
     * @param end   结束大小(不包含)
     * @return 整数列表
     */
    public static List<Integer> range(int start, int end) {
        return unfold(start, integer -> integer + 1, integer -> integer < end);
    }

    /**
     * 按指定条件过滤出集合中的元素
     *
     * @param collection 目标集合
     * @param predicate  结果元素所满足的断言
     * @return 过滤后的列表
     */
    public static <T> List<T> filter(@NonNull Collection<T> collection, @NonNull Predicate<? super T> predicate) {
        return new ArrayList<>(foldLeft(collection, new LinkedList<>(), l -> t -> {
            if (predicate.test(t)) {
                l.add(t);
            }
            return l;
        }));
    }

    /**
     * 统计集合中满足条件的元素个数
     *
     * @param collection 目标集合
     * @param predicate  条件对应的断言
     * @return 满足条件的元素个数
     */
    public static <T> int count(Collection<T> collection, Predicate<? super T> predicate) {
        return foldLeft(collection, 0, i -> t -> predicate.test(t)
                ? i + 1
                : i);
    }

    /**
     * 判断集合中是否包含满足指定条件的元素
     *
     * @param collection 目标集合
     * @param predicate  条件对应的断言
     * @return 如果包含就返回true,否则返回false
     */
    public static <T> boolean contains(Collection<T> collection, Predicate<? super T> predicate) {
        return foldAny(collection, predicate, t -> true).getOrElse(false);
    }

    public static <T, U> U reduce(Collection<T> list, U identity, BiFunction<U, T, U> f) {
        return foldLeft(list, identity, u -> t -> f.apply(u, t));
    }

    /* 集合拼接 */
    @SafeVarargs
    public static <T> List<T> concat(@Nullable List<T> list, @Nullable List<T>... lists) {
        List<T> resultList = list == null ? new ArrayList<>() : new ArrayList<>(list);
        if (lists != null && lists.length > 0) {
            for (List<T> l : lists) {
                if (isNotEmpty(l)) {
                    resultList.addAll(l);
                }
            }
        }
        return resultList;
    }

    /**
     * 将函数function执行count次,并将结果收集到列表中
     *
     * @param count    执行的次数
     * @param function 要执行的函数
     * @return 收集的结果
     */
    public static <T> List<T> doTimes(int count, Function<? super Integer, T> function) {
        ArrayList<T> list = new ArrayList<>(count);
        for (int i = 0; i < count; i++) {
            list.add(function.apply(i));
        }
        return list;
    }

    /**
     * 将过程consumer执行count次,忽略结果
     *
     * @param count    执行的次数
     * @param consumer 要执行的过程
     */
    public static void doTimes(int count, Consumer<? super Integer> consumer) {
        for (int i = 0; i < count; i++) {
            consumer.accept(i);
        }
    }

    /* 确保List不为null*/
    @NonNull
    public static <T> List<T> ensure(List<T> list) {
        return list == null ? new ArrayList<>() : list;
    }

    /* 确保Set不为null */
    @NonNull
    public static <T> Set<T> ensure(Set<T> set) {
        return set == null ? new HashSet<>() : set;
    }

    /*确保Map不为null*/
    public static <K, V> Map<K, V> ensure(Map<K, V> map) {
        return map == null ? new HashMap<>() : map;
    }
}



版权声明:本文为zssrxt原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。