Use of emptyIterator in java [duplicate] - java

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.

Related

How to get Map.values as a Set rather than a Collection?

I have a map Map<String, SomeType> where every instance of SomeType is added by name like map.put(object.getName(), object). In the end, there are no duplicates in map.values().
Now, I want a Set<SomeType> from this map without making a copy like new HashSet<>(map.values()).
Is this possible, preferential only with the standard library?
You already know how to do it with new HashSet<>(map.values()). You can't get a Set of the values directly, since the values can contain duplicates. Even if in your specific Map there are no duplicate values, in a general Map there can be duplicate values.
You can do something with Java 8 Streams, but it has no advantage over instantiating the Set explicitly.
Set<SomeType> values = map.values().stream().collect(Collectors.toSet());
Without a Collection wrapper it is not possible.
Just because in your case there are no duplications, that does not mean they cannot be.
Java Collections API allow you to put duplicate values in the Map, so the contract has to return Collection and not Set.
It would be a simple matter to create a Set view of any Collection.
public final class SetView<E> extends AbstractSet<E> {
private final Collection<? extends E> collection;
private SetView(Collection<? extends E> collection) {
this.collection = collection;
}
public static <E> SetView<E> of(Collection<? extends E> collection) {
return new SetView<>(collection);
}
#Override
public boolean contains(Object e) {
return collection.contains(e);
}
// rest omitted.
}
With this, you could then write Set<E> set = SetView.of(map.values()); and all changes to the Map would automatically be reflected in the Set.
The problem with this approach is that some methods would be difficult to implement without copying the Collection. For example, how would you write size()?
The most sensible way is
#Override
public int size() {
return new HashSet<>(collection).size();
}
but this defeats the purpose of using a view rather than just copying the elements in the first place. If you know that the Collection will never contain duplicates, you could simply do
#Override
public int size() {
return collection.size();
}
However I would advise against such an approach. A Map is allowed to contain duplicate values, and the possibility of adding two entries with the same value means that the contract for Set would be broken.
Unless you have very good reason for not wanting to copy the elements, I would just use new HashSet<>(map.values()).

Collections with limited size [duplicate]

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.

Which is good practice - Modifying a List in the method, or returning a new List in the method?

Example code:
modifyMyList(myList);
public void modifyMyList(List someList){
someList.add(someObject);
}
or:
List myList = modifyMyList(myList);
public List modifyMyList(List someList){
someList.add(someObject)
return someList;
}
There is also a 3rd option I believe: You can create a new List in modifyMyList method and return this new List...
( 3rd option is here, I was too lazy but someone already added it in the answers: )
List myList = modifyMyList(myList);
public List modifyMyList(List someList){
List returnList = new ArrayList();
returnList.addAll(someList);
returnList.add(someObject);
return Collections.unmodifiableList(returnList);
}
Is there any reason why I should choose one over another? What should be considered in such case?
I have a (self imposed) rule which is "Never mutate a method parameter in a public method". So, in a private method, it's ok to mutate a parameter (I even try to avoid this case too). But when calling a public method, the parameters should never be mutated and should be considered immutable.
I think that mutating method arguments is a bit hacky and can lead to bugs that are harder to see.
I have been known to make exceptions to this rule but I need a really good reason.
Actually there is no functional difference.
You'll come to know the difference when you want the returned list
List someNewList = someInstnace.modifyMyList(list);
The second is probably confusing as it implies a new value is being created and returned - and it isn't.
An exception would be if the method was part of a 'fluent' API, where the method was an instance method and was modifying its instance, and then returning the instance to allow method chaining: the Java StringBuilder class is an example of this.
In general, however, I wouldn't use either.
I'd go for your third option: I write a method that creates and returns a new list with the appropriate change. This is a bit artificial in the case of your example, as the example is really just reproducing List.add(), but...
/** Creates a copy of the list, with val appended. */
public static <T> List<T> modifyMyList(List<T> list, T val) {
List<T> xs = new ArrayList<T>(list);
xs.add(val);
return xs;
}
Aside: I wouldn't, as suggested by Saket return an immutable list. His argument for immutability and parallelism is valid. But most of the time Java programmers expect to be able to modify a collection, except in special circumstances. By making you method return an immutable collection, you limit it's reusability to such circumstances. (The caller can always make the list immutable if they want to: they know the returned value is a copy and won't be touched by anything else.) Put another way: Java is not Clojure. Also, if parallelism is a concern, look at Java 8 and streams (the new kind - not I/O streams).
Here's a different example:
/** Returns a copy of a list sans-nulls. */
public static <T> List<T> compact(Iterable<T> it) {
List<T> xs = new ArrayList<T>();
for(T x : it)
if(x!=null) xs.add(x);
return xs;
}
Note that I've genercized the method and made it more widely applicable to taking an Iterable instead of a list. In real code, I'd have two overloaded versions, one taking an Iterable and one an Iterator. (The first would be implemented by calling the second, with the iterable's iterator.) Also, I've made it static as there was no reason for your method to be an instance method (it does not depend on state from the instance).
Sometimes, though, if I'm writing library code, and if it is not clear whether a mutating or non-mutating implementation is more generally useful, I create both. Here's a fuller example:
/** Returns a copy of the elements from an Iterable, as a List, sans-nulls. */
public static <T> List<T> compact(Iterable<T> it) {
return compact(it.iterator());
}
public static <T> List<T> compact(Iterator<T> iter) {
List<T> xs = new ArrayList<T>();
while(iter.hasNext()) {
T x = iter.next();
if(x!=null) xs.add(x);
}
return xs;
}
/** In-place, mutating version of compact(). */
public static <T> void compactIn(Iterable<T> it) {
// Note: for a 'fluent' version of this API, have this return 'it'.
compactIn(it.iterator());
}
public static <T> void compactIn(Iterator<T> iter) {
while(iter.hasNext()) {
T x = iter.next();
if(x==null) iter.remove();
}
}
If this was in a real API I'd check the arguments for null and throw IllegalArgumentException. (NOT NullPointerException - though it is often used for this purpose. NullPointerException happens for other reasons as well, e.g. buggy code. IllegalArgumentException is better for invalid parameters.)
(There'd also be more Javadoc than actual code too!)
The first and second solution are very similar, The advantage of the second is to permit chaining. The question of "is it a good practise" is subjected to debate as we can see here:
Method Chaining in Java
So the real question is between the first solution with mutable list and the third with a unmutable list, and again, there is not a unique response, it is the same debate between returning String, which are immutable and using Stringbuffer, which are mutable but permits better performance.
If you need reliablility of your API , and if you don't have performance issues use immutable (the third solution). Use it if your lists are always small.
If you need only performance use a mutable list (the first solution)
I will recommend creating a new list in the method and returning an immutable list. That way your code will work even when you are passed in an Immutable list. It is generally a good practice to create immutable objects as we generally move towards functional programming and try to scale across multiple processor architectures.
List myList = modifyMyList(myList);
public List modifyMyList(List someList){
List returnList = new ArrayList();
returnList.addAll(someList);
returnList.add(someObject);
return Collections.unmodifiableList(returnList);
}
As I said in my other answer, I don't think you should mutate the list parameter. But there are times where you also don't want to take a copy of the original list and mutate the copy.
The original list might be large so the copy is expensive
You want the copy to be kept up-to-date with any updates to the original list.
In these scenarios, you could create a MergedList which is a view over two (or perhaps more) lists
import java.util.*;
public class MergedList<T> extends AbstractList<T> {
private final List<T> list1;
private final List<T> list2;
public MergedList(List<T> list1, List<T> list2) {
this.list1 = list1;
this.list2 = list2;
}
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
Iterator<T> it1 = list1.iterator();
Iterator<T> it2 = list1.iterator();
#Override
public boolean hasNext() {
return it1.hasNext() || it2.hasNext();
}
#Override
public T next() {
return it1.hasNext() ? it1.next() : it2.next();
}
};
}
#Override
public T get(int index) {
int size1 = list1.size();
return index < size1 ? list1.get(index) : list2.get(index - size1);
}
#Override
public int size() {
return list1.size() + list2.size();
}
}
The you could do
public List<String> modifyMyList(List<String> someList){
return new MergedList(someList, List.of("foo", "bar", "baz"));
}
Both ways will work because in this case java works with the reference of the List but i prefer the secound way because this solution works for pass by value too, not only for pass by reference.
Functionally both are same.
However when you expose your method as an API, second method may give an impression that it returns a new modified list other than the original passed list.
While the first method would make it clear (of-course based on method naming convention) that it will modify the original list (Same object).
Also, the second method returns a list, so ideally the caller should check for a null return value even if the passed list is non null (The method can potentially return a null instead of modified list).
Considering this I generally prefer to use method one over second.

Check ArrayList<String> contains("") method with equalsIgnoreCase [duplicate]

This question already has answers here:
ArrayList contains case sensitivity
(20 answers)
Closed 9 years ago.
I have an ArrayList();
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("BBB");
list.add("cCc");
System.out.println(list.contains("aAa"));
Here i want to check contains() method with equalsIgnoreCase method in same line.
How can i do it?
boolean containsEqualsIgnoreCase(Collection<String> c, String s) {
for (String str : c) {
if (s.equalsIgnoreCase(str)) {
return true;
}
}
return false;
}
You can't. The contract of contains is that it defers to equals. That's a fundamental part of the Collection interface. You have to write a custom method that iterates through the list and checks each value.
This is an interesting question from an OO perspective.
One possibility is to transfer the responsibility of the contract you want to enforce (equality without case) to the collected elements themselves, not to the list, with respect to a proper separation of concern.
You would then add a new class for your String objects (without inheritance, String class is final) where you would implement your own hashCode/equals contract.
// Strictly speaking, this is not a String without case, since only
// hashCode/equals methods discard it. For instance, we would have
// a toString() method which returns the underlying String with the
// proper case.
public final class StringWithoutCase {
private final String underlying;
public StringWithoutCase(String underlying) {
if (null == underlying)
throw new IllegalArgumentException("Must provide a non null String");
this.underlying = underlying;
}
// implement here either delegation of responsibility from StringWithoutCase
// to String, or something like "getString()" otherwise.
public int hashCode() {
return underlying.toLowerCase().hashCode();
}
public boolean equals(Object other) {
if (! (other instanceof StringWithoutCase))
return false;
return underlying.equalsIgnoreCase(other.underlying);
}
}
The objects populating the collection would be instances of StringWithoutCase :
Collection<StringWithoutCase> someCollection = ...
someCollection.add(new StringWithoutCase("aaa"));
someCollection.add(new StringWithoutCase("BBB"));
someCollection.add(new StringWithoutCase("cCc"));

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