Combine multiple Collections into a single logical Collection? - java

Assume, I have a constant number of collections (e.g. 3 ArrayLists) as members of a class. Now, I want to expose all the elements to other classes so they can simply iterate over all elements (ideally, read only).
I'm using guava collections and I wonder how I could use guava iterables/iterators to generate a logical view on the internal collections without making temporary copies.

With Guava, you can use Iterables.concat(Iterable<T> ...), it creates a live view of all the iterables, concatenated into one (if you change the iterables, the concatenated version also changes). Then wrap the concatenated iterable with Iterables.unmodifiableIterable(Iterable<T>) (I hadn't seen the read-only requirement earlier).
From the Iterables.concat( .. ) JavaDocs:
Combines multiple iterables into a
single iterable. The returned iterable
has an iterator that traverses the
elements of each iterable in inputs.
The input iterators are not polled
until necessary. The returned
iterable's iterator supports remove()
when the corresponding input iterator
supports it.
While this doesn't explicitly say that this is a live view, the last sentence implies that it is (supporting the Iterator.remove() method only if the backing iterator supports it is not possible unless using a live view)
Sample Code:
final List<Integer> first = Lists.newArrayList(1, 2, 3);
final List<Integer> second = Lists.newArrayList(4, 5, 6);
final List<Integer> third = Lists.newArrayList(7, 8, 9);
final Iterable<Integer> all =
Iterables.unmodifiableIterable(
Iterables.concat(first, second, third));
System.out.println(all);
third.add(9999999);
System.out.println(all);
Output:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 9999999]
Edit:
By Request from Damian, here's a similar method that returns a live Collection View
public final class CollectionsX {
static class JoinedCollectionView<E> implements Collection<E> {
private final Collection<? extends E>[] items;
public JoinedCollectionView(final Collection<? extends E>[] items) {
this.items = items;
}
#Override
public boolean addAll(final Collection<? extends E> c) {
throw new UnsupportedOperationException();
}
#Override
public void clear() {
for (final Collection<? extends E> coll : items) {
coll.clear();
}
}
#Override
public boolean contains(final Object o) {
throw new UnsupportedOperationException();
}
#Override
public boolean containsAll(final Collection<?> c) {
throw new UnsupportedOperationException();
}
#Override
public boolean isEmpty() {
return !iterator().hasNext();
}
#Override
public Iterator<E> iterator() {
return Iterables.concat(items).iterator();
}
#Override
public boolean remove(final Object o) {
throw new UnsupportedOperationException();
}
#Override
public boolean removeAll(final Collection<?> c) {
throw new UnsupportedOperationException();
}
#Override
public boolean retainAll(final Collection<?> c) {
throw new UnsupportedOperationException();
}
#Override
public int size() {
int ct = 0;
for (final Collection<? extends E> coll : items) {
ct += coll.size();
}
return ct;
}
#Override
public Object[] toArray() {
throw new UnsupportedOperationException();
}
#Override
public <T> T[] toArray(T[] a) {
throw new UnsupportedOperationException();
}
#Override
public boolean add(E e) {
throw new UnsupportedOperationException();
}
}
/**
* Returns a live aggregated collection view of the collections passed in.
* <p>
* All methods except {#link Collection#size()}, {#link Collection#clear()},
* {#link Collection#isEmpty()} and {#link Iterable#iterator()}
* throw {#link UnsupportedOperationException} in the returned Collection.
* <p>
* None of the above methods is thread safe (nor would there be an easy way
* of making them).
*/
public static <T> Collection<T> combine(
final Collection<? extends T>... items) {
return new JoinedCollectionView<T>(items);
}
private CollectionsX() {
}
}

Plain Java 8 solutions using a Stream.
Constant number
Assuming private Collection<T> c, c2, c3.
One solution:
public Stream<T> stream() {
return Stream.concat(Stream.concat(c.stream(), c2.stream()), c3.stream());
}
Another solution:
public Stream<T> stream() {
return Stream.of(c, c2, c3).flatMap(Collection::stream);
}
Variable number
Assuming private Collection<Collection<T>> cs:
public Stream<T> stream() {
return cs.stream().flatMap(Collection::stream);
}

If you're using at least Java 8, see my other answer.
If you're already using Google Guava, see Sean Patrick Floyd's answer.
If you're stuck at Java 7 and don't want to include Google Guava, you can write your own (read-only) Iterables.concat() using no more than Iterable and Iterator:
Constant number
public static <E> Iterable<E> concat(final Iterable<? extends E> iterable1,
final Iterable<? extends E> iterable2) {
return new Iterable<E>() {
#Override
public Iterator<E> iterator() {
return new Iterator<E>() {
final Iterator<? extends E> iterator1 = iterable1.iterator();
final Iterator<? extends E> iterator2 = iterable2.iterator();
#Override
public boolean hasNext() {
return iterator1.hasNext() || iterator2.hasNext();
}
#Override
public E next() {
return iterator1.hasNext() ? iterator1.next() : iterator2.next();
}
};
}
};
}
Variable number
#SafeVarargs
public static <E> Iterable<E> concat(final Iterable<? extends E>... iterables) {
return concat(Arrays.asList(iterables));
}
public static <E> Iterable<E> concat(final Iterable<Iterable<? extends E>> iterables) {
return new Iterable<E>() {
final Iterator<Iterable<? extends E>> iterablesIterator = iterables.iterator();
#Override
public Iterator<E> iterator() {
return !iterablesIterator.hasNext() ? Collections.emptyIterator()
: new Iterator<E>() {
Iterator<? extends E> iterableIterator = nextIterator();
#Override
public boolean hasNext() {
return iterableIterator.hasNext();
}
#Override
public E next() {
final E next = iterableIterator.next();
findNext();
return next;
}
Iterator<? extends E> nextIterator() {
return iterablesIterator.next().iterator();
}
Iterator<E> findNext() {
while (!iterableIterator.hasNext()) {
if (!iterablesIterator.hasNext()) {
break;
}
iterableIterator = nextIterator();
}
return this;
}
}.findNext();
}
};
}

You could create a new List and addAll() of your other Lists to it. Then return an unmodifiable list with Collections.unmodifiableList().

Here is my solution for that:
EDIT - changed code a little bit
public static <E> Iterable<E> concat(final Iterable<? extends E> list1, Iterable<? extends E> list2)
{
return new Iterable<E>()
{
public Iterator<E> iterator()
{
return new Iterator<E>()
{
protected Iterator<? extends E> listIterator = list1.iterator();
protected Boolean checkedHasNext;
protected E nextValue;
private boolean startTheSecond;
public void theNext()
{
if (listIterator.hasNext())
{
checkedHasNext = true;
nextValue = listIterator.next();
}
else if (startTheSecond)
checkedHasNext = false;
else
{
startTheSecond = true;
listIterator = list2.iterator();
theNext();
}
}
public boolean hasNext()
{
if (checkedHasNext == null)
theNext();
return checkedHasNext;
}
public E next()
{
if (!hasNext())
throw new NoSuchElementException();
checkedHasNext = null;
return nextValue;
}
public void remove()
{
listIterator.remove();
}
};
}
};
}

Related

Predicate generic method

I wrote a Predicate code that takes any Object and tests it for the following conditions:
if Object type is String and contains "k" then it should return true.
if Object type is Integer and greater than 100 then it should return true.
if Object type is Employee which is class and having salary of employee greater than 60000, it should return true.
After writing that Predicate method I wrote the remove method that removes values from list according to Predicate method.
public class ConditionalRemove {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>(Arrays.asList("ramesh", "kushal", "suresh", "kc"));
System.out.println(conditionalRemove(list));
}
public static <T> List<T> conditionalRemove(ArrayList<T> list) {
ConditionCheck<T> cond = new ConditionCheck<>();
for (T t : list) {
if (cond.test(t)) {
list.remove(t);
}
}
return list;
}
static class ConditionCheck<T> implements Predicate<T> {
#Override
public boolean test(T t) {
if (t instanceof String) {
return (((String) t).contains("k"));
} else if (t instanceof Integer) {
return ((int) t > 100);
} else if (t instanceof Employee) {
return ((int) ((Employee) t).getSalary() < 60000);
}
return true;
}
}
}
After compiling this code I found Exception in thread "main" java.util.ConcurrentModificationException
The issue is you are updating the list when you are iterating over that. The issue can be fixed by updating code as
public static <T> List<T> conditionalRemove(ArrayList<T> list) {
ConditionCheck<T> cond = new ConditionCheck<>();
Iterator it = list.iterator();
while(it.hasNext())
{
it.next();
if (cond.test(t)) {
it.remove();
}
}
return list;
}
Since you're using Java 8, a functional approach would be to create a new filtered list:
public static <T> List<T> conditionalRemove(ArrayList<T> list) {
return list.stream()
.filter(new ConditionCheck<>())
.collect(Collectors.toList());
}
You can even replace the static inner class by just a method:
public static <T> List<T> conditionalRemove(ArrayList<T> list) {
return list.stream()
.filter(ConditionalRemove::test)
.collect(Collectors.toList());
}
private static <T> boolean test(T t) {
// your predicate implementation...
}
Don't reinvent the wheel: Use Collection#removeIf():
public static <T> List<T> conditionalRemove(ArrayList<T> list) {
list.removeIf(new ConditionCheck<>());
return list;
}
At one line, this is hardly worth the effort of creating a method to call... just make the single line call in-line:
public static void main(String[] args) {
List<String> list = new ArrayList<>(Arrays.asList("ramesh", "kushal", "suresh", "kc"));
list.removeIf(new ConditionCheck<>());
System.out.println(list);
}
Some data structures throws the java.util.ConcurrentModificationException when you modify them during an iteration, in order to do that with success you need use a synchronized structure such as "CopyOnWriteArrayList", this is the java doc reference
Hope this can help you!
Regards.

Iterator and iterable for an 2D array Java

I have created two iterators for an array: the first runs the array by rows (iteratorRow) and then by columns and the second, first by columns and then by rows (iteratorColumn).
I have another class, Matrix, in which I must create two methods for performing iteration (iteratorRowColumn and iteratorColumnRow) that return iterators that have created to be accessible to other classes.
The array must implement the Iterable interface and may be configured (using a Boolean) which of the two iterators it shall be refunded by calling iterator () method.
How can I do that? Do I have to do some getters methods? Something like this?
public Iterator iteratorRowColumn () {
return new iteratorRow;
}
I think that the last sentence of assignment explains a problem very well. I am not sure what part of it is unclear so let me explain in detail:
The array must implement the Iterable interface
public class Matrix<T> implements Iterable<T>
may be configured (using a Boolean)
public Matrix(boolean defaultRowColumnIterator) {
this.defaultRowColumnIterator = defaultRowColumnIterator;
}
which of the two iterators it shall be returning by calling iterator() method
#Override
public Iterator<T> iterator() {
return defaultRowColumnIterator ? iteratorRowColumn() : iteratorColumnRow();
}
Here is a compilable example:
public class Matrix<T> implements Iterable<T> {
T[][] array;
boolean defaultRowColumnIterator;
public Matrix(boolean defaultRowColumnIterator) {
this.defaultRowColumnIterator = defaultRowColumnIterator;
}
// other methods and constructors
public Iterator<T> iteratorRowColumn() {
return null; // your current implementation
}
public Iterator<T> iteratorColumnRow() {
return null; // your current implementation
}
#Override
public Iterator<T> iterator() {
return defaultRowColumnIterator ? iteratorRowColumn() : iteratorColumnRow();
}
}
Something like this:
public class Proba {
Integer[][] array = new Integer[10][10];
public class MyIter implements Iterator<Integer> {
private Integer[] integers;
private int index = 0;;
public MyIter(Integer[] integers) {
this.integers = integers;
}
#Override
public boolean hasNext() {
return index < integers.length -1 ;
}
#Override
public Integer next() {
return integers[index];
}
#Override
public void remove() {
//TODO: remove
}
}
public static void main(String[] args) {
Iterator<Integer> iter = new Proba().getIterator(1);
while (iter.hasNext()) {
System.out.println(iter.next());
}
}
public Iterator<Integer> getIterator(int row) {
return new MyIter(array[row]);
}
}

How to turn FibSupplier into a generic FiniteSupplier?

Considering I have the following class:
public class Problem2 extends Problem<Integer> {
#Override
public void run() {
result = toList(new FibSupplier(i -> (i <= 4_000_000)))
.stream()
.filter(i -> (i % 2 == 0))
.mapToInt(i -> i)
.sum();
}
#Override
public String getName() {
return "Problem 2";
}
private static <E> List<E> toList(final Iterator<E> iterator) {
List<E> list = new ArrayList<>();
while (iterator.hasNext()) {
list.add(iterator.next());
}
return list;
}
private class FibSupplier implements Iterator<Integer> {
private final IntPredicate hasNextPredicate;
private int beforePrevious = 0;
private int previous = 1;
public FibSupplier(final IntPredicate hasNextPredicate) {
this.hasNextPredicate = hasNextPredicate;
}
#Override
public boolean hasNext() {
return hasNextPredicate.test(previous);
}
#Override
public Integer next() {
int result = beforePrevious + previous;
beforePrevious = previous;
previous = result;
return result;
}
}
}
If you take a look at FibSupplier you can see that it exposes a generalized problem, even though it has a specialized implementation here, what I've managed to extract are:
It has a Predicate.
It has initial variables.
It has a variable that needs to be tested by the predicate.
It has a custom next() method.
My attempt to generalize this was with the following, note that I use a generic version for now instead of a specialized integer version:
public class FiniteSupplier<E> implements Iterator<E> {
private final Predicate<E> predicate;
public FiniteSupplier(final Predicate<E> predicate) {
this.predicate = predicate;
}
#Override
public boolean hasNext() {
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public E next() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
I want to be able to call FiniteSupplier with a predicate, however now I do not really know how to implement the other requirements I have managed to extract. I understand it could be done by extending the FiniteSupplier and making it abstract, but is that the correct way to do it?
The method test(int/Integer) can be used as Predicate<Integer> and as IntPredicate. The compiler does the conversion:
IntPredicate ip = (i) -> i>0;
Predicate<Integer> pi = (i) -> i>0;
Predicate<Integer> ip2pi = ip::test;
IntPredicate pi2ip = pi::test;
But you can't cast the two types as they are not assignable. IntPredicate does not extend Predicate.
So just use ::test when you create FibSupplier:
new FibSupplier(p) => new FibSupplier(p::test)
Or do that in a constructor. I'd introduce a new abstract type FiniteIntSupplier with an extra constructor that takes an IntSupplier and converts it to a general Supplier:
public FiniteIntSupplier(IntPredicate p) {
this(p::test);
}

How to make a set backed by a map?

There is a method in the Collections class.
Set<E> Collections.newSetFromMap(<backing map>)
What does it mean by the backing map and the set backed by a map?
Perhaps it would be illuminating to look at the implementation:
private static class SetFromMap<E> extends AbstractSet<E>
implements Set<E>, Serializable
{
private final Map<E, Boolean> m; // The backing map
private transient Set<E> s; // Its keySet
SetFromMap(Map<E, Boolean> map) {
if (!map.isEmpty())
throw new IllegalArgumentException("Map is non-empty");
m = map;
s = map.keySet();
}
public void clear() { m.clear(); }
public int size() { return m.size(); }
public boolean isEmpty() { return m.isEmpty(); }
public boolean contains(Object o) { return m.containsKey(o); }
public boolean remove(Object o) { return m.remove(o) != null; }
public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }
public Iterator<E> iterator() { return s.iterator(); }
public Object[] toArray() { return s.toArray(); }
public <T> T[] toArray(T[] a) { return s.toArray(a); }
public String toString() { return s.toString(); }
public int hashCode() { return s.hashCode(); }
public boolean equals(Object o) { return o == this || s.equals(o); }
public boolean containsAll(Collection<?> c) {return s.containsAll(c);}
public boolean removeAll(Collection<?> c) {return s.removeAll(c);}
public boolean retainAll(Collection<?> c) {return s.retainAll(c);}
// addAll is the only inherited implementation
private static final long serialVersionUID = 2454657854757543876L;
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException
{
stream.defaultReadObject();
s = m.keySet();
}
}
Edit - added explanation:
The map that you provide is used as the m field in this object.
When you add an element e to the set, it adds an entry e -> true to the map.
public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }
So this class turns your Map into an object that behaves like a Set by simply ignoring the values that things are mapped to, and just using the keys.
I just made an example code for you
HashMap<String, Boolean> map = new HashMap<String, Boolean>();
Set<String> set = Collections.newSetFromMap(map);
System.out.println(set);
for (int i = 0; i < 10; i++)
map.put("" + i, i % 2 == 0);
System.out.println(map);
System.out.println(set);
and the output
[]
{3=false, 2=true, 1=false, 0=true, 7=false, 6=true, 5=false, 4=true, 9=false, 8=true}
[3, 2, 1, 0, 7, 6, 5, 4, 9, 8]
Simply put, Collections.newSetFromMap uses the provided Map<E> implementation to store the Set<E> elements.
The Set internally uses Map to store the values. Here the backing map refers to the set map which is internally used by the set.
For more information.
http://www.jusfortechies.com/java/core-java/inside-set.php

Maximum Size List in Java

It's useful to me to have a data structure in Java that has all the functionality of a List, but has a maximum storage capacity, and drops older data when newer data is added. Conceivably at some point I might want to implement a fixed size Queue which keeps a more general ordering of the data, and drops the old data lowest in that ordering, but that's the for the future.
At the moment I'm implementing it like this:
public class FixedSizeList<T> {
private final int maxSize;
private final LinkedList<T> list = new LinkedList<T>();
public FixedSizeQueue(int maxSize) {
this.maxSize = maxSize < 0 ? 0 : maxSize;
}
public T add(T t) {
list.add(t);
return list.size() > maxSize ? list.remove() : null;
}
// add remaining methods...
}
Is there either (a) an existing data structure that serves my needs, or (b) a better way of implementing this data structure?
I would use array and 2 indexes for head and tail of the list.Make sure that head is always < tail and you're safe.
Here's a List with a size limit, based on Guava's ForwardingList:
A list which forwards all its method
calls to another list. Subclasses
should override one or more methods to
modify the behavior of the backing
list as desired per the decorator
pattern.
Guava has base classes like this for all JDK-5 Collection types. Each of them fulfills the same purpose: making it easy to add value, while delegating all default functionality to the underlying collection.
public class LimitingList<E> extends ForwardingList<E> {
private final class LimitingListIterator extends ForwardingListIterator<E> {
private final ListIterator<E> innerListIterator;
private LimitingListIterator(final ListIterator<E> innerListIterator) {
this.innerListIterator = innerListIterator;
}
/**
* {#inheritDoc}
*/
#Override
public void add(final E element) {
if (inner.size() < maxSize)
innerListIterator.add(element);
else
throw new IndexOutOfBoundsException();
}
#Override
protected ListIterator<E> delegate() {
return innerListIterator;
}
}
public LimitingList(final int maxSize) {
this(new ArrayList<E>(), maxSize);
}
public LimitingList(final List<E> inner, final int maxSize) {
super();
this.inner = inner;
this.maxSize = maxSize;
}
#Override
public boolean addAll(final Collection<? extends E> collection) {
boolean changed = false;
for (final E item : collection) {
final boolean tmpChanged = add(item);
changed = changed || tmpChanged;
if (!tmpChanged)
break;
}
return changed;
}
#Override
public boolean add(final E e) {
if (inner.size() < maxSize)
return super.add(e);
else
return false;
}
#Override
public ListIterator<E> listIterator() {
return new LimitingListIterator(inner.listIterator());
}
#Override
public void add(final int index, final E element) {
throw new UnsupportedOperationException();
}
#Override
public boolean addAll(final int index, final Collection<? extends E> elements) {
throw new UnsupportedOperationException();
}
#Override
public ListIterator<E> listIterator(final int index) {
return new LimitingListIterator(inner.listIterator(index));
}
private final int maxSize;
private final List<E> inner;
#Override
protected List<E> delegate() {
return inner;
}
}
It delegates all real functionality to an underlying list, which is an ArrayList per default (single argument constructor), but you can also supply (two argument constructor)
Unless you want to use an actual array, I don't believe there is a list type data structure you can use.
Personally I would extend one of the existing list classes to get the functionality, and override the add methods. This way you get all the other list operations for free. ie something like the following...
public class FixedSizeArrayList<T> extends ArrayList<T> {
private final int maxSize;
public FixedSizeArrayList(int maxSize) {
super();
this.maxSize = maxSize
}
public boolean add(T t) {
if (size() >= maxSize) {
remove(0);
}
return super.add(t);
}
// implementation of remaining add methods....
}
If you extend the LinkedList class you will have direct access to all it's methods. Instead of having to write stuff like
fixedList.getList().pop()
you could just write
fixedList.pop()
You could then override the methods where you need to add the maxSize criteria.

Categories

Resources