001/* Copyright (C) 2013 TU Dortmund 002 * This file is part of AutomataLib, http://www.automatalib.net/. 003 * 004 * AutomataLib is free software; you can redistribute it and/or 005 * modify it under the terms of the GNU Lesser General Public 006 * License version 3.0 as published by the Free Software Foundation. 007 * 008 * AutomataLib is distributed in the hope that it will be useful, 009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 011 * Lesser General Public License for more details. 012 * 013 * You should have received a copy of the GNU Lesser General Public 014 * License along with AutomataLib; if not, see 015 * http://www.gnu.de/documents/lgpl.en.html. 016 */ 017package net.automatalib.commons.util.collections; 018 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.Collections; 022import java.util.Iterator; 023import java.util.List; 024import java.util.NoSuchElementException; 025import java.util.RandomAccess; 026 027/** 028 * Various methods for operating on collections. 029 * 030 * @author Malte Isberner <malte.isberner@gmail.com> 031 * 032 */ 033public abstract class CollectionsUtil { 034 035 /* 036 * Prevent inheritance. 037 */ 038 private CollectionsUtil() { 039 } 040 041 /** 042 * Adds all elements from an iterable to a collection. 043 * @param <E> element class. 044 * @param coll the collection to which the elements are added. 045 * @param it the iterable providing the elements to add. 046 * @return <code>true</code> if the collection was modified, 047 * <code>false</code> otherwise. 048 */ 049 public static <E> boolean addAll(Collection<E> coll, Iterable<? extends E> it) { 050 boolean modified = false; 051 for(E e : it) 052 modified = coll.add(e) || modified; 053 return modified; 054 } 055 056 /** 057 * Retrieves an unmodifiable list only containing null values 058 * of the given size. 059 * @param size the size 060 * @return a list consisting of the specified number of <tt>null</tt> values 061 */ 062 @SuppressWarnings("unchecked") 063 public static <E> List<E> nullList(int size) { 064 return (List<E>)(List<?>)new NullList(size); 065 } 066 067 public static <E> E removeReplace(List<E> list, int index) { 068 int lastIdx = list.size() - 1; 069 E last = list.remove(lastIdx); 070 if(lastIdx != index) { 071 list.set(index, last); 072 return last; 073 } 074 return null; 075 } 076 077 public static List<Integer> intRange(int start, int end) { 078 return new IntRange(start, end); 079 } 080 081 public static List<Integer> intRange(int start, int end, int step) { 082 return new IntRange(start, end, step); 083 } 084 085 public static List<Character> charRange(char start, char end) { 086 return new CharRange(start, end); 087 } 088 089 public static <T> List<? extends T> randomAccessList(Collection<? extends T> coll) { 090 if(coll instanceof List && coll instanceof RandomAccess) 091 return (List<? extends T>)coll; 092 return new ArrayList<>(coll); 093 } 094 095 096 public static <T> Iterable<List<T>> allTuples(final Iterable<T> domain, final int minLength, final int maxLength) { 097 // Check if domain is empty 098 // If it is, then the empty tuple (if not excluded by minLength > 0) is still part of the result 099 // Otherwise, the result is empty 100 if(!domain.iterator().hasNext()) { 101 if(minLength == 0) 102 return Collections.singletonList(Collections.<T>emptyList()); 103 return Collections.<List<T>>emptyList(); 104 } 105 106 return new Iterable<List<T>>() { 107 @Override 108 public Iterator<List<T>> iterator() { 109 return new AllTuplesIterator<>(domain, minLength, maxLength); 110 } 111 }; 112 } 113 114 public static <T> Iterable<List<T>> allTuples(final Iterable<T> domain, final int length) { 115 return allTuples(domain, length, length); 116 } 117 118 @SafeVarargs 119 public static <T> Iterable<List<T>> allCombinations(final Iterable<T> ...iterables) { 120 if(iterables.length == 0) 121 return Collections.singletonList(Collections.<T>emptyList()); 122 123 return new Iterable<List<T>>() { 124 @Override 125 public Iterator<List<T>> iterator() { 126 try { 127 return new AllCombinationsIterator<>(iterables); 128 } 129 catch(NoSuchElementException ex) { 130 // FIXME: Special case if one of the iterables is empty, then the whole set 131 // of combinations is empty. Maybe handle this w/o exception? 132 return Collections.<List<T>>emptySet().iterator(); 133 } 134 } 135 }; 136 } 137 138}