package com.framework.core.utils;

import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * List去除重复数据的五种方式
 */
public class RemoveRepeatDataUtil {


    /**
     * 1.使用LinkedHashSet删除arrayList中的重复数据
     * LinkedHashSet是一个再ArrayList删除重复数据的最佳方法。
     * LinkedHashSet在内部完成两件事情：
     * a.删除重复数据
     * b.保持添加到其中的数据的顺序
     *
     * @param t 入参
     * @param <T> 返回数据类型
     * @return array
     */
    public <T> ArrayList<T> linkedHashSet(T[] t) {
        ArrayList<T> arrayList = new ArrayList<>(Arrays.asList(t));
//        System.out.println("源数组：" + arrayList);
        LinkedHashSet<T> hashSet = new LinkedHashSet<>(arrayList);
        return new ArrayList<>(hashSet);
    }


    /**
     * 2. 使用Java8新特性stream进行List去重
     *  使用stream的distinct()方法返回一个由不同数据组成的流，通过对象的equals()方法进行比较。
     *  收集所有区域数据List使用Collectors.toList();
     *  在不使用Set的情况下，从Java中的arrayList中删除重复项。
     *
     * @param t 入参
     * @param <T> 返回数据类型
     * @return array
     */
    public <T> List<T> stream(T[] t) {
        ArrayList<T> arrayList = new ArrayList<>(Arrays.asList(t));
        Collector<T, ?, List<T>> collectors = Collectors.toList();
        Stream<T> stream = arrayList.stream();
        Stream<T> distinct = stream.distinct();
        return distinct.collect(collectors);
    }

    /**
     * 3. 利用HashSet不能添加重复数据的特性。
     * 由于HashSet不能保证添加顺序，所以只能作为判断条件保证顺序。
     *
     * @param t 入参
     * @param <T> 返回数据类型
     * @return array
     */
    public <T> List<T> hashSet(T[] t) {
        List<T> list = new ArrayList<>(Arrays.asList(t));
        HashSet<T> hashSet = new HashSet<>(list.size());
        List<T> result = new ArrayList<>(list.size());
        for (T value: list ) {
            if(hashSet.add(value)){
                result.add(value);
            }
        }
        list.clear();
        list.addAll(result);
        return list;
    }

    /**
     * 4. 利用List的contains方法循环遍历，重新排序，只添加一次数据，避免重复。
     *
     * @param t 入参
     * @param <T> 返回数据类型
     * @return array
     */
    public <T> List<T> containsFor(T[] t) {
        List<T> list = new ArrayList<>(Arrays.asList(t));
        List<T> result = new ArrayList<>(list.size());
        for (T value: list ) {
            if(!result.contains(value)) {
                result.add(value);
            }
        }
        list.clear();
        list.addAll(result);
        return list;
    }

    /**
     * 5.双重for循环去重
     *
     * @param t 入参
     * @param <T> 返回数据类型
     * @return array
     */
    public <T> List<T> twinFor(T[] t) {
        List<T> list = new ArrayList<>(Arrays.asList(t));
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j < list.size(); j++) {
                if(i != j && list.get(i) == list.get(j)){
                    list.remove(list.get(j));
                }
            }
        }
        return list;
    }

}

