CollectionTools.java
package eu.javaexperience.collection;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import eu.javaexperience.collection.map.KeyVal;
import eu.javaexperience.collection.map.PublisherMap;
import eu.javaexperience.interfaces.simple.SimpleGet;
import eu.javaexperience.interfaces.simple.getBy.GetBy1;
import eu.javaexperience.interfaces.simple.getBy.GetBy2;
import eu.javaexperience.interfaces.simple.publish.SimplePublish2;
import eu.javaexperience.semantic.references.MayNull;
public class CollectionTools
{
public static <T> boolean containsIdentical(Collection<T> coll, T elem)
{
for(T e:coll)
if(e == elem)
return true;
return false;
}
public static String toString(Collection<?> coll)
{
if(coll == null)
return "null";
StringBuilder sb = new StringBuilder();
sb.append("[");
for(Object o:coll)
{
if(sb.length() > 1)
sb.append(",");
sb.append(o);
}
sb.append("]");
return sb.toString();
}
public static String toStringMultiline(Collection<?> coll)
{
if(coll == null)
return "null";
StringBuilder sb = new StringBuilder();
sb.append("[");
for(Object o:coll)
{
sb.append(o);
sb.append(",\n");
}
sb.append("]");
return sb.toString();
}
public static <T,U extends Collection<T>,R extends Collection<U>> R shard(Collection<T> coll, int num_per_unit, SimpleGet<U> fact, SimpleGet<R> retType)
{
R ret = retType.get();
int n = 0;
U crnt = fact.get();
ret.add(crnt);
for(T e: coll)
if(++n > num_per_unit)
{
crnt = fact.get();
ret.add(crnt);
crnt.add(e);
n = 0;
}
else
crnt.add(e);
return ret;
}
public static <T> T getMaxOccurrenceElementByEquals(Collection<T> coll)
{
Map<T,Integer> map = getElementOccurrenceByEquals(coll);
T ret = null;
int max = 0;
for(Entry<T, Integer> kv:map.entrySet())
if(kv.getValue() > max)
{
max = kv.getValue();
ret = kv.getKey();
}
return ret;
}
public static <T> void removeNulls(Collection<T> coll)
{
Iterator<T> it = coll.iterator();
while(it.hasNext())
if(it.next() == null)
it.remove();
}
public static boolean containsNull(Collection<?> coll)
{
for(Object e:coll)
if(e == null)
return true;
return false;
}
public static <T> Map<T,Integer> getElementOccurrenceByEquals(Collection<T> coll)
{
Map<T,Integer> ret = new HashMap<>();
for(T e:coll)
{
Integer i = ret.get(e);
i = i==null?1:++i;
ret.put(e, i);
}
return ret;
}
public static <T,D extends Collection<T>> D copyInto(Collection<T> src, D dst)
{
for(T a:src)
{
dst.add(a);
}
return dst;
}
public static <D extends Collection<T>, T> D copyInto(T[] src, D dst)
{
for(T a:src)
dst.add(a);
return dst;
}
public static <T> void copyReverseInto(T[] src, Collection<T> dst)
{
for(int i=src.length-1;i>=0;--i)
{
dst.add(src[i]);
}
}
public static <T> boolean addLikeSet(Collection<T> coll, T element)
{
if(!coll.contains(element))
{
return coll.add(element);
}
return false;
}
public static <T> T tryGetFirst(Collection<T> coll)
{
if(null == coll)
{
return null;
}
for(T c:coll)
{
return c;
}
return null;
}
//Sub-case of tryGetFirst(Collection), but it doesn't need to create an iterator
public static <T> T tryGetFirst(List<T> coll)
{
if(null == coll)
{
return null;
}
if(coll.isEmpty())
{
return null;
}
return coll.get(0);
}
public static <C, T> Collection<T> extractTo(Collection<T> dst, Collection<? extends C> src, GetBy1<T, C> extractor)
{
for(C c: src)
{
dst.add(extractor.getBy(c));
}
return dst;
}
/**
* if `maybe_collection` is a collection, then add the subject to it,
* else create a new one add add both to.
* if it's null, it will __not__ be added to the collection
*
* */
public static <T> Collection<T> addOrWrap
(
Object maybe_collection,
SimpleGet<Collection<T>> create,
T subject
)
{
if(maybe_collection instanceof Collection)
{
((Collection) maybe_collection).add(subject);
return (Collection) maybe_collection;
}
else
{
Collection<T> c = create.get();
if(null != maybe_collection)
{
c.add((T) maybe_collection);
}
if(null != subject)
{
c.add(subject);
}
return c;
}
}
public static <E, C extends Collection<E>> C inlineAdd
(
C coll,
E... elem
)
{
for(E e:elem)
{
coll.add(e);
}
return coll;
}
public static <E, C extends Collection<E>> C inlineAdd
(
C coll,
Collection<E> elem
)
{
for(E e:elem)
{
coll.add(e);
}
return coll;
}
public static <K,V> Map<K, V> mapLikeEntryIntoCollection(final Collection<Entry<K, V>> dst)
{
return new PublisherMap<K, V>()
{
@Override
public V put(K key, V value)
{
dst.add(new KeyVal<K, V>(key, value));
return null;
}
@Override
public void putAll(Map<? extends K, ? extends V> m)
{
for(java.util.Map.Entry<? extends K, ? extends V> kv:m.entrySet())
{
dst.add((java.util.Map.Entry<K, V>) kv);
}
}
};
}
public static <SRC,C extends Collection<T>, T> C executeWith
(
SimpleGet<? extends C> carrier_creator,
SimplePublish2<? extends C, ? extends SRC> transformer,
SRC src
)
{
C ret = carrier_creator.get();
((SimplePublish2)transformer).publish(ret, src);
return ret;
}
public static <T> T randomItem(List<T> coll)
{
return coll.get((int) (Math.random()*coll.size()));
}
public static <T> boolean containsExternal
(
Collection<T> coll,
T key,
GetBy2<Boolean, T, T> eq
)
{
for(T t:coll)
{
if(Boolean.TRUE == eq.getBy(key, t))
{
return true;
}
}
return false;
}
public static <T> List<T> tryWrapToList(Object object, String name)
{
if(object instanceof List)
{
return (List<T>) object;
}
else if(object instanceof Collection)
{
ArrayList<T> ret = new ArrayList<>();
copyInto((Collection)object, ret);
return ret;
}
else if(object.getClass().isArray())
{
ArrayList<T> ret = new ArrayList<>();
int len = Array.getLength(object);
for(int i=0;i<len;++i)
{
ret.add((T)Array.get(object, i));
}
return ret;
}
throw new RuntimeException(name+" is not a collection or array");
}
public static <S, D, R extends Collection<D>, G extends Collection<S>> R transaformInto
(
R dst,
G from,
GetBy1<D, S> converter
)
{
for(S f:from)
{
dst.add(converter.getBy(f));
}
return dst;
}
public static <T> String toString
(
Collection<T> elems,
@MayNull String glue,
GetBy1<String, T> elemAppend
)
{
StringBuilder sb = new StringBuilder();
int i = 0;
for(T e:elems)
{
if(null != glue && ++i > 1)
{
sb.append(glue);
}
sb.append(elemAppend.getBy(e));
}
return sb.toString();
}
public static <S, D> D[] convert(Class<D> dst, Collection<S> src, GetBy1<D, S> converter)
{
D[] ret = (D[]) Array.newInstance(dst, src.size());
int i = 0;
for(S s:src)
{
ret[i++] = converter.getBy(s);
}
return ret;
}
public static <C extends Collection<D>, S, D> C convert(C dst, Collection<S> src, GetBy1<D, S> converter)
{
for(S s:src)
{
dst.add(converter.getBy(s));
}
return dst;
}
public static <T> void reverse(List<T> list, int fromInclusive, int toInclusive)
{
while(fromInclusive < toInclusive)
{
Collections.swap(list, fromInclusive++, toInclusive--);
}
}
/**
* https://codeforces.com/blog/entry/3980
**/
public static <C extends Comparable<C>> boolean nextPermutation(List<C> c)
{
// 1. finds the largest k, that c[k] < c[k+1]
int first = -1;
for(int i=c.size()-2; i>= 0;--i)
{
if(c.get(i).compareTo(c.get(i + 1)) < 0 )
{
first = i;
break;
}
}
if(first == -1)
{
return false; // no greater permutation
}
// 2. find last index toSwap, that c[k] < c[toSwap]
int toSwap = c.size() - 1;
while(c.get(first).compareTo(c.get(toSwap)) >= 0)
{
--toSwap;
}
// 3. swap elements with indexes first and last
Collections.swap( c, first++, toSwap );
// 4. reverse sequence from k+1 to n (inclusive)
toSwap = c.size() - 1;
while ( first < toSwap )
{
Collections.swap(c, first++, toSwap--);
}
return true;
}
public static <T> ArrayList<T> inlineArrayList(T... elems)
{
return inlineAdd(new ArrayList<>(), elems);
}
}