Collections with limited size [duplicate] - java

This question already has answers here:
Define a fixed-size list in Java
(14 answers)
Closed 8 years ago.
Is there any collection which allows me limit the number of elements allowed?
What I need is a collection with size of 5 elements, when this collection is full, a new element can be added, but the oldest element of this collection will be replaced for the new element.

You can extend an old good ArrayList (or any other implementation which fits you the best).
import java.util.ArrayList;
public class LimitedCollection<E> extends ArrayList<E> {
public static final int MAX_ELEMENTS = 2;
#Override
public boolean add(E e) {
if (this.size() < MAX_ELEMENTS) {
return super.add(e);
} else {
return false;
}
}
}

You can do this with majority of the Collections available in java.utils package.
You can do this,sample for List Collection:
List<X> list = Arrays.asList(new X[desiredSize]);
// where X is any Object type (including arrays and enums,
// but excluding primitives)
The resulting list is modifiable, but not resizable (i.e. add(e) and remove(e) don't work, but set(index, e) does).

Either Guava EvictingQueue or Apache common-collections should do the job for you.

Related

Is there a way to avoid loops when adding to a list?

I was wondering a code like this:
List<String> list = new ArrayList<String>();
for(CustomObject co : objects) {
list.add(co.getActualText());
}
Can it be written differently? I mean of course at some point there will be a loop but I am wondering if there is an API usage I am ignoring
If you use Java 8, you can take advantage of the Stream API:
List<String> list = objects.stream()
.map(CustomObject::getActualText)
.collect(Collectors.toList());
If you have Java 8, what about:
objects.forEach(item -> list.add(item.getActualText()));
Internally still a loop though.
EDIT a little Off-Topic: IMO This is the most readable and best solution. Why not just use a foreach you might ask. The answer: Because this way the collection chooses the best way to iterate over the items. For example, ArrayList does not use an iterator, because it knows better than you:
#Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
#SuppressWarnings("unchecked")
final E[] elementData = (E[]) this.elementData;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
action.accept(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
Of course, Apache Commons and Guava also provide ways to avoid loops without using Java 8.
Commons CollectionUtils.collect:
CollectionUtils.collect(objects, Transformer.invokerTransformer("getActualText"), list);
Guava Lists.transform:
List<String> list = Lists.transform(objects,
new Function<CustomObject, String>() {
public String apply(CustomObject co) {
return co.getActualText();
}
}
);
Although clearly a bit of a ridiculous suggestion: you could avoid loops by adding them recursively.
void add(List<? super String> receiver, CustomObject[] objects) {
addRec(receiver, toAdd, 0, objects.length());
}
void addRec(List<? super String> receiver, CustomObject[] objects, int start, int end) {
if (start + 1 == end) {
receiver.add(objects[start].getActualText());
} else if (start != end) {
int mid = (start + end) / 2;
addRec(receiver, objects, start, mid);
addRec(receiver, objects, mid, end);
}
}
If you use Eclipse Collections you can write the following as of Java 8:
MutableList<CustomObject> objects = ...
MutableList<String> result = objects.collect(CustomObject::getActualText);
With Java 5 - 7 you can use an anonymous inner class representing the SAM type Function with the collect method.
MutableList<CustomObject> objects = ...
MutableList<String> result = objects.collect(new Function<CustomObject, String>() {
public String valueOf(CustomObject object){
return object.getActualText();
}
});
Note: I am a committer for Eclipse Collections
Using streams would be more idiomatic in Java 8, but if you like it to be closer to the conventional loop based approach you can use forEach:
objects.forEach(co -> list.add(co.getActualText()) );
To achieve really good efficiency when copying a range of data between two types of lists that are unknown to each other, there must be a mechanism by which a "trusted" type can ask each to expose the backing array(s) associated with a range of elements, and then use a bulk-copy operation to move data from one to the other. It would be possible to write such a class entirely in Java, by having a GetArraySource method pass to the constructor of a trusted ArraySource class an object it could use to request the backing array associated with a particular element (the return would include the backing array and the range of elements included therein). The code wanting the copy would call GetArraySource, and pass the ArraySource returned thereby to the destination list's CopyFromArraySource method which could then ask the ArraySource to copy one or more ranges of items into its own backing array(s).
If ArraySource was a class supplied with Java, and Oracle documented exactly what it would do with arrays that it received, then it would be possible for types like ArrayList and String to expose their contents as an ArraySource, or accept outside data from an ArraySource, without improperly exposing their array to any code that might abuse it.
Unfortunately, unless Oracle incorporates such a thing into the Java distribution, support will probably be too sparse to be useful. It does not good to have the source list support one such class, the destination support another, and the code wanting the copy operation a third. All three classes need to support the same particular trusted-array-segment-copy-helper class.

Use of emptyIterator in java [duplicate]

This question already has answers here:
Java iterator over an empty collection of a parameterized type
(7 answers)
Closed 8 years ago.
Can anyone let me know what is the real time use of an Empty Iterator in java? I'm curious to know why is it needed?
things like,
1. public static <T> Iterator<T> emptyIterator()
2. public static <T> ListIterator<T> emptyListIterator()
3. public static final <T> Set<T> emptySet(), etc..
source: http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#emptyIterator()
You can use an empty iterator in cases where an API that you implement requires an iterator, but some of your code's logic can yield no items in the result. In that case, instead of returning a null, you return an empty iterator. You can also use an empty iterator to save some memory and for testing purposes.
Here is some example code that prevents returning null and saves some memory at the same time:
class LazyObjectInitialization {
private Collection<String> items;
public final Iterator<String> items() {
if(items == null || items.isEmpty()) {
return Collections.emptyIterator();
}
return items.iterator();
}
public final add(String item) {
if(items == null) {
items = new ArrayList<>();
}
items.add(item);
}
}
In the above class, the field items is not initialized until an element is added. So to provide expected behavior in method items() we return an empty iterator. The benefit from this are as follow:
Smaller memory consumption
The class allocates memory only when it is really needed.
Smaller memory mutation
Until we add something to the object, we never create a new instance of the iterator.
We never return null.

Function with multiple outputs in Java [duplicate]

This question already has answers here:
How to return multiple objects from a Java method?
(25 answers)
Closed 9 years ago.
How to create a JAVA function with multiple outputs?
Something like:
private (ArrayList<Integer[]>, int indexes) sortObjects(ArrayList<Integer[]> arr) {
//...
}
Java's not like Python - no tuples. You have to create an Object and wrap all your outputs into it. Another solution might be a Collection of some sort, but I think the former means better encapsulation.
In some cases it is possible to use method arguments to handle result values. In your case, part of the result is a list (which may be updated destructively). So you could change your method-signature to the following form:
private int sortObjects(ArrayList<Integer[]> input, ArrayList<Integer[]> result) {
int res = 0;
for (Integer[] ints : input) {
if (condition(ints) {
result.add(calculatedValue);
res++
}
}
return res;
}
You cannot, you can either
Create a wrapper return object
Create multiple functions
Use an object as return value.
class SortedObjects { private ArrayList<Integer[]> _first; int _indexes; ...getter/setter/ctor... }
private SortedObjects sortObjects(ArrayList<Integer[]> arr) { ... }
You cannot.
The simple solution is to return an array of objects. A more robust solution is to create a class for holding the response, and use getters to get the individual values from the response object returned by your code.
You have to create a class which includes member variables for each piece of information you require, and return an object of that class.
Another approach is to use an Object which wraps the collection.
class SortableCollection {
final List<Integer[]> tables = ...
int indexes = -1;
public void sortObjects() {
// perform sort on tables.
indexes = ...
}
}
As it operates on a mutable object, there is no arguments or return values.

How to get the capacity of the ArrayList in Java?

Its known that Java ArrayList is implemented using arrays and initializes with capacity of 10 and increases its size by 50% . How to get the current ArrayList capacity not the Size of the ArrayList.
Thx
I don't think this is possible. What is your use case? I believe C# ArrayLists have a .capacity property, but the Java ArrayList class doesn't expose this information.
You have the constructor that takes an initial capacity argument, and you have the ensureCapacity() method which you could use to reduce the amount of incremental reallocation.
You also have the trimToSize() method you can use if you are really worried about memory usage.
You can get it by reflection:
public abstract class ArrayListHelper {
static final Field field;
static {
try {
field = ArrayList.class.getDeclaredField("elementData");
field.setAccessible(true);
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
#SuppressWarnings("unchecked")
public static <E> int getArrayListCapacity(ArrayList<E> arrayList) {
try {
final E[] elementData = (E[]) field.get(arrayList);
return elementData.length;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
You can get the current capacity of an ArrayList in Java using reflection. Here is an example:
package examples1;
import java.util.ArrayList;
import java.util.List;
import java.lang.reflect.Field;
public class Numbers {
public static void main(String[] args) throws Exception {
List<Integer> numbers = new ArrayList<>();
numbers.add(1);
System.out.println(getCapacity(numbers));
}
static int getCapacity(List al) throws Exception {
Field field = ArrayList.class.getDeclaredField("elementData");
field.setAccessible(true);
return ((Object[]) field.get(al)).length;
}
}
This will output: 10
Notes:
getCapacity() method modified from the original at http://javaonlineguide.net/2015/08/find-capacity-of-an-arraylist-in-java-size-vs-capacity-in-java-list-example.html
Note that the default capacity of 10 is granted after the first add to the list. If you try this before adding, you will get an output of 0
To force a capacity without adding, pass it in the constructor like so:
List<Integer> numbers = new ArrayList<>(20);
Looking at ArrayList's spec I see no method that provides this information.
That said, the ensureCapacity method does seem like a step in the right direction (caution: it is does not guarantee a correct answer): When called it ensures that the capacity is at least the specified argument. So, if the ArrayList implementation uses this method to ensure capacity (as opposed to calling some private method/manipulating the relevant fields directly) you can obtain the current capacity by overriding this method. You also need to override trimToSize() in a similar manner.
Of course, this solution is not very portable as a different implementation of ArrayList (on a JVM from another vendor) may do things differently.
Here's how the code should look like
public class CapacityTrackingArrayList<T> extends ArrayList<T> {
// declare a constructor for each ArrayList constructor ...
// Now, capacity tracking stuff:
private int currentCapacity = 10;
public int getCapacity() { return currentCapacity; }
public void ensureCapacity(int arg) {
currentCapacity = arg;
super.ensureCapacity(arg);
}
public void trimToSize() { currentCapacity = size(); super.trimToSize(); }
}
You can use Vector instead of ArrayList. Vector supports capacity() method.
The whole point of using ArrayList is to dynamically add new element, So there is no specific method to get the capacity of the ArrayList.
Every time we add an element dynamically causes reallocation and since reallocation is costly in terms of time, preventing reallocation improves performance and hence you can manually increase the capacity of ArrayList by calling ensureCapacity() but again you can not find out the capacity of the ArrayList.
Default capacity of ArrayList is 10.once the max size is reached,new capacity will be:
new capacity=(currentcapacity*3/2)+1.
Don't remember if it has but you could do it yourself by looking at the source code of ArrayList. Java developers should take advantage of the source code bundled with the SDK.
I just checked out the sun documentation on the ArrayList class, and the only method I saw that related to the capacity was ensureCapacity(int minCapacity), which is not exactly what you want. Good luck!
The default capacity is 2 for an Array List in java. I am not able to find the vague documentation I read a while ago. But the size will be zero upon initialization.
Once we add the third element it will creates an array of double the capacity in another memory location. The reference will be shifted accordingly and the previous array will be garbage collected

A collection that represents a concatenation of two collections in Java

Is there a class that represents the concatenation of a collection with another collection? This class should be a Collection in itself, and should delegate all methods to the underlying (inner) collections - no extra memory should be allocated, nor any of the original collections modified.
Example usage:
Collection<String> foo = ...
Collection<String> bar = ...
// this should be O(1) memory and time
Collection<String> combined = concat(foo, bar);
if (combined.contains("Zee"))
...
for (String str : combined)
System.out.println(str);
As always for any collections stuff, look at google-collections. If you have Sets, specifically (not just a general collection), you want:
Set<String> combined = Sets.union(foo, bar);
which creates an unmodifiable view of the two sets. That is, changes in foo or bar will be reflected in combined (but combined.add() etc is not supported).
For the more generic case, you have Iterables.concat() but that merely lets you iterate over the joined item, the Iterable interface obviously doesn't include contains so you're a little hosed there.
The other collections utilities classes in google-collections (com.google.common.collect.Lists and com.google.common.collect.Collections2) don't contain any concatenation methods. Don't see why they couldn't, but at the moment they don't.
Your question is very vague. Especially "with another item another collection" is quite unclear.
You can at least add the contents of another Collection to the current Collection using Collection#addAll(). Here Collection can be anything of its subinterfaces/implementations, e.g. List or Set.
Example:
List<String> foos = Arrays.asList("foo1", "foo2", "foo3");
List<String> bars = Arrays.asList("bar1", "bar2", "bar3");
foos.addAll(bars); // Now foos contains everything.
Edit: Or do you actually want to create a new Collection based on an existing Collection and then add a new item to it? In this case just construct a new Collection with the existing Collection as constructor argument. E.g.:
List<String> foos = Arrays.asList("foo1", "foo2", "foo3");
List<String> bars = new ArrayList<String>(foos);
bars.add("bar"); // Now bars contains everything.
There is not, but writing it yourself should be straight forward
package ch.akuhn.util;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Concat {
public static <T> Iterable<T> all(final Iterable<T>... iterables) {
return new Iterable<T>() {
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
Iterator<Iterable<T>> more = Arrays.asList(iterables).iterator();
Iterator<T> current = more.hasNext() ? more.next().iterator() : null;
#Override
public boolean hasNext() {
if (current == null) return false;
if (current.hasNext()) return true;
current = more.hasNext() ? more.next().iterator() : null;
return this.hasNext();
}
#Override
public T next() {
if (!hasNext()) throw new NoSuchElementException();
return current.next();
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
}
And then
for (Object each: Concat.all(collection,whatever,etcetera,...)) {
// ...
}
Just wrote this code here, compile at your own risk!
PS, if you gonna write unit tests for this class, send 'em to me.
I think what you're asking for is a Java construct that allows you to put collections together without modifying the original collections. In other words, you have collections A and B, both of size N and M respectively. After the concat call, you still have collections A and B and their sizes are still N and M, however you have collection C as well which points to A and B, making its size N+M.
The answer is no, Java doesn't have anything out of the box that does this... However you could write a quick wrapper that wraps a series of collections and add those collections to it. (All it would do is maintain references to each of the collections) and you could expose get/insert methods as needed.
Apache Commons Collections also has a more general CompositeCollection class which can be used as an interface to an arbitrary number of Collections.
I'm not sure what your asking. My interpretation of your question is that your looking for the add method on the Collection. I don't think that's what you're asking though.
Try InterleavingEnumeration or apache's commons collections' ListUtils (ListUtils.union())

Categories