
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