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

ru.greatbit.utils.collection.CollectionUtils Maven / Gradle / Ivy

The newest version!
package ru.greatbit.utils.collection;

import ru.greatbit.utils.serialize.JsonSerializer;
import ru.greatbit.utils.string.StringUtils;

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

import static java.util.stream.Collectors.toList;

/**
 * Created by azee on 4/29/14.
 */
public class CollectionUtils {

    /**
     * Merge lists
     * @param first - List
     * @param second - List
     * @param  - Object class
     * @return - List
     */
    public static  List mergeLists(List first, List second){
        HashSet set = new LinkedHashSet<>(first);
        set.addAll(second);

        //Keep initial list class
        first.clear();
        first.addAll(set);
        return first;
    }

    /**
     * Merge lists of object
     * Objects are compared by serialisation value
     * @param first - The first list of objects
     * @param second - The second list of objects
     * @return - Merged list of objects
     * @param  - Object class
     * @throws Exception - Serialization exceptions
     */
    public static  List mergeListsByValue(List first, List second) throws Exception {
        Map dataMap = listToMD5Map(first);
        for (T object : second){
            dataMap.put(StringUtils.getMd5String(JsonSerializer.marshal(object)), object);
        }
        return dataMap.values().stream().collect(toList());
    }



    /**
     * Get differences of lists
     * Objects should override hashCode and equals so they could be
     * compared in HashMap to find differences
     * @param first - List
     * @param second - List
     * @param  - Object class
     * @return Difference object
     */
    public static Difference getDiff(List first, List second){
        return getDiff(listToMap(first), listToMap(second));
    }

    /**
     * Get differences of lists
     * Uses serialised objects md5 - it will work slower
     * but can process objects if hashCode and equals can't be overridden
     * @param first - first list
     * @param second - second list
     * @return - Difference object
     * @param  - Object class
     * @throws Exception - Serialization exception
     */
    public static Difference getDiffAnyObject(List first, List second) throws Exception {
        return getDiff(listToMD5Map(first), listToMD5Map(second));
    }

    /**
     * Return a difference from 2 maps
     * @param firstMap - First map do diff
     * @param secondMap - Second map do diff
     * @param  - Key class
     * @param  - Value class
     * @return - Difference object
     */
    private static Difference getDiff(Map firstMap, Map secondMap){
        Difference difference = new Difference();

        secondMap.entrySet().forEach(entry ->{
            V value = firstMap.get(entry.getKey());
            if (value == null){
                difference.getAdded().add(entry.getValue());
            } else {
                difference.getEqual().add(value);
            }
        });

        firstMap.entrySet().forEach(entry -> {
            V value = secondMap.get(entry.getKey());
            if (value == null){
                difference.getRemoved().add(entry.getValue());
            }
        });
        return difference;
    }

    /**
     * Load a list to a map
     * @param input - List
     * @param  - Object class
     * @return - Map
     */
    public static  Map listToMap(List input){
        Map dataMap = new LinkedHashMap();
        input.forEach(value -> dataMap.put(value, value));
        return dataMap;
    }

    /**
     * Load a list to a map, use serialised objects md5 - it will work slower
     * but can process objects if hashCode and equals can't be overridden
     * @param input - List of objects
     * @return - Map of objects by md5 key
     * @param  - Object class
     * @throws Exception - Serialization exceptions
     */
    public static  Map listToMD5Map(List input) throws Exception {
        Map dataMap = new LinkedHashMap();
        for (T object : input){
            dataMap.put(StringUtils.getMd5String(JsonSerializer.marshal(object)), object);
        }
        return dataMap;
    }

    /**
     * Used to remove values from lists that don't support remove method
     * @param input - List
     * @param index - Index to remove
     * @param  - Object class
     * @return - Result list with removed item
     */
    public static  List removeByIndex(List input, int index) {
        List result = new LinkedList(input);
        result.remove(index);

        //Doing that to keep original input class
        if (input.getClass().getName().equals("java.util.Arrays$ArrayList")){
            input = (List) Arrays.asList(result.toArray());
        } else {
            input.clear();
            input.addAll(result);
        }
        return input;
    }

    /**
     * Remove duplicate values of list from map
     * @param values - Map of values
     * @param  - Object class
     * @param  - Key
     * @return - Result Map without duplcates
     */
    public static  Map> removeDuplicateValues(Map> values) {
        if (values == null){
            return values;
        }
        values.entrySet().forEach(entry ->{
            entry.setValue(entry.getValue().stream().distinct().collect(toList()));
        });
        return values;
    }

    /**
     * Remove duplicate values from list, equals() will be used to compare objects
     * @param values - List of values to filter
     * @param  - Object class
     * @return - Filtered list
     */
    public static  List removeDuplicateValues(List values) {
        if (values == null){
            return values;
        }
        return values.stream().distinct().collect(toList());
    }

    /**
     * Remove duplicate values from list by values fetched in meaningValue function
     * @param values - List of values to filter
     * @param  - Object class
     * @return - Filtered list
     */
    public static  List removeDuplicateValues(List values, Function meaningValue) {
        if (values == null){
            return values;
        }
        return values.stream().map(value -> new Wrapper(value, meaningValue))
                .distinct()
                .map(wrapper -> wrapper.getObject())
                .collect(toList());
    }

    /**
     * Reorder a list of elements by another list. Trying to keep absolute order of initial list
     * but reorder regarding to provided relative order list.
     * E.g. initial was [1, 2, 3, 4, 5] - calling reorder with list [2, 5, 4] will generate list
     * [1, 2, 3, 5, 4]
     * @param elements - initial list
     * @param order - list describing relative order
     * @param  - Class of comparable object
     * @return - new reordered list
     */
    public static  List reorder(List elements, List order){
        if (order.size() == 0){
            return elements;
        }
        if (elements.size() == 0){
            return order;
        }

        Map elementsIndexMap = new HashMap<>();
        for(int i = 0; i < elements.size(); i++){
            elementsIndexMap.put(elements.get(i), i);
        }

        Set merged = new LinkedHashSet<>();
        Set elementsSet = new HashSet<>(elements);
        int i = 0;
        int j = 0;
        T currElement = elements.get(i);
        T currOrder = order.get(j);
        while(i < elements.size() || j < order.size()){
            if (j >= order.size()){
                merged.addAll(elements.subList(i, elements.size()));
                break;
            }
            currElement = i < elements.size() ? elements.get(i) : currElement;
            currOrder = j < order.size() ? order.get(j) : currOrder;

            Integer currElementIndex = elementsIndexMap.get(currElement);
            Integer currOrderIndexInElements = elementsIndexMap.get(currOrder);
            currOrderIndexInElements = currOrderIndexInElements == null ? elements.size() : currOrderIndexInElements;

            if (currElementIndex.compareTo(currOrderIndexInElements) < 0){
                merged.add(currElement);
                i++;
            }
            if (currOrderIndexInElements.compareTo(currElementIndex) < 0 || i >= elements.size()){
                if (merged.contains(currOrder)){
                    merged.remove(currOrder);
                }
                if (elementsSet.contains(currOrder)){
                    merged.add(currOrder);
                }
                j++;
            }
            if (currElementIndex.compareTo(currOrderIndexInElements) == 0){
                merged.add(currElement);
                i++;
                j++;
            }
        }
        return new ArrayList<>(merged);
    }

    /**
     * Swap two elements in list
     * @param elements - list of elements
     * @param i - index of first element
     * @param j - index of second element
     * @param  - elements class
     */
    public static  void swap(List elements, int i, int j) {
        T buff = elements.get(j);
        elements.set(j, elements.get(i));
        elements.set(i, buff);
    }



}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy