I know about SortedSet, but in my case I need something that implements List, and not Set. So is there an implementation out there, in the API or elsewhere?
It shouldn't be hard to implement myself, but I figured why not ask people here first?
There's no Java collection in the standard library to do this. LinkedHashSet<E> preserves ordering similarly to a List, though, so if you wrap your set in a List when you want to use it as a List you'll get the semantics you want.
Alternatively, the Commons Collections (or commons-collections4, for the generic version) has a List which does what you want already: SetUniqueList / SetUniqueList<E>.
Here is what I did and it works.
Assuming I have an ArrayList to work with the first thing I did was created a new LinkedHashSet.
LinkedHashSet<E> hashSet = new LinkedHashSet<E>()
Then I attempt to add my new element to the LinkedHashSet. The add method does not alter the LinkedHasSet and returns false if the new element is a duplicate. So this becomes a condition I can test before adding to the ArrayList.
if (hashSet.add(E)) arrayList.add(E);
This is a simple and elegant way to prevent duplicates from being added to an array list. If you want you can encapsulate it in and override of the add method in a class that extends the ArrayList. Just remember to deal with addAll by looping through the elements and calling the add method.
So here's what I did eventually. I hope this helps someone else.
class NoDuplicatesList<E> extends LinkedList<E> {
#Override
public boolean add(E e) {
if (this.contains(e)) {
return false;
}
else {
return super.add(e);
}
}
#Override
public boolean addAll(Collection<? extends E> collection) {
Collection<E> copy = new LinkedList<E>(collection);
copy.removeAll(this);
return super.addAll(copy);
}
#Override
public boolean addAll(int index, Collection<? extends E> collection) {
Collection<E> copy = new LinkedList<E>(collection);
copy.removeAll(this);
return super.addAll(index, copy);
}
#Override
public void add(int index, E element) {
if (this.contains(element)) {
return;
}
else {
super.add(index, element);
}
}
}
Why not encapsulate a set with a list, sort like:
new ArrayList( new LinkedHashSet() )
This leaves the other implementation for someone who is a real master of Collections ;-)
You should seriously consider dhiller's answer:
Instead of worrying about adding your objects to a duplicate-less List, add them to a Set (any implementation), which will by nature filter out the duplicates.
When you need to call the method that requires a List, wrap it in a new ArrayList(set) (or a new LinkedList(set), whatever).
I think that the solution you posted with the NoDuplicatesList has some issues, mostly with the contains() method, plus your class does not handle checking for duplicates in the Collection passed to your addAll() method.
I needed something like that, so I went to the commons collections and used the SetUniqueList, but when I ran some performance test, I found that it seems not optimized comparing to the case if I want to use a Set and obtain an Array using the Set.toArray() method.
The SetUniqueTest took 20:1 time to fill and then traverse 100,000 Strings comparing to the other implementation, which is a big deal difference.
So, if you worry about the performance, I recommend you to use the Set and Get an Array instead of using the SetUniqueList, unless you really need the logic of the SetUniqueList, then you'll need to check other solutions...
Testing code main method:
public static void main(String[] args) {
SetUniqueList pq = SetUniqueList.decorate(new ArrayList());
Set s = new TreeSet();
long t1 = 0L;
long t2 = 0L;
String t;
t1 = System.nanoTime();
for (int i = 0; i < 200000; i++) {
pq.add("a" + Math.random());
}
while (!pq.isEmpty()) {
t = (String) pq.remove(0);
}
t1 = System.nanoTime() - t1;
t2 = System.nanoTime();
for (int i = 0; i < 200000; i++) {
s.add("a" + Math.random());
}
s.clear();
String[] d = (String[]) s.toArray(new String[0]);
s.clear();
for (int i = 0; i < d.length; i++) {
t = d[i];
}
t2 = System.nanoTime() - t2;
System.out.println((double)t1/1000/1000/1000); //seconds
System.out.println((double)t2/1000/1000/1000); //seconds
System.out.println(((double) t1) / t2); //comparing results
}
Regards,
Mohammed Sleem
My lastest implementation: https://github.com/marcolopes/dma/blob/master/org.dma.java/src/org/dma/java/util/UniqueArrayList.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
/**
* Extends <tt>ArrayList</tt> and guarantees no duplicate elements
*/
public class UniqueArrayList<T> extends ArrayList<T> {
private static final long serialVersionUID = 1L;
public UniqueArrayList(int initialCapacity) {
super(initialCapacity);
}
public UniqueArrayList() {
super();
}
public UniqueArrayList(T[] array) {
this(Arrays.asList(array));
}
public UniqueArrayList(Collection<? extends T> col) {
addAll(col);
}
#Override
public void add(int index, T e) {
if (!contains(e)) super.add(index, e);
}
#Override
public boolean add(T e) {
return contains(e) ? false : super.add(e);
}
#Override
public boolean addAll(Collection<? extends T> col) {
Collection set=new LinkedHashSet(this);
set.addAll(col);
clear();
return super.addAll(set);
}
#Override
public boolean addAll(int index, Collection<? extends T> col) {
Collection set=new LinkedHashSet(subList(0, index));
set.addAll(col);
set.addAll(subList(index, size()));
clear();
return super.addAll(set);
}
#Override
public T set(int index, T e) {
return contains(e) ? null : super.set(index, e);
}
/** Ensures element.equals(o) */
#Override
public int indexOf(Object o) {
int index=0;
for(T element: this){
if (element.equals(o)) return index;
index++;
}return -1;
}
}
Off the top of my head, lists allow duplicates. You could quickly implement a UniqueArrayList and override all the add / insert functions to check for contains() before you call the inherited methods. For personal use, you could only implement the add method you use, and override the others to throw an exception in case future programmers try to use the list in a different manner.
The documentation for collection interfaces says:
Set — a collection that cannot contain duplicate elements.
List — an ordered collection (sometimes called a sequence). Lists can contain duplicate elements.
So if you don't want duplicates, you probably shouldn't use a list.
in add method, why not using HashSet.add() to check duplicates instead of HashSet.consist().
HashSet.add() will return true if no duplicate and false otherwise.
What about this?
Just check the list before adding with a contains for an already existing object
while (searchResult != null && searchResult.hasMore()) {
SearchResult nextElement = searchResult.nextElement();
Attributes attributes = nextElement.getAttributes();
String stringName = getAttributeStringValue(attributes, SearchAttribute.*attributeName*);
if(!List.contains(stringName)){
List.add(stringName);
}
}
I just made my own UniqueList in my own little library like this:
package com.bprog.collections;//my own little set of useful utilities and classes
import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
/**
*
* #author Jonathan
*/
public class UniqueList {
private HashSet masterSet = new HashSet();
private ArrayList growableUniques;
private Object[] returnable;
public UniqueList() {
growableUniques = new ArrayList();
}
public UniqueList(int size) {
growableUniques = new ArrayList(size);
}
public void add(Object thing) {
if (!masterSet.contains(thing)) {
masterSet.add(thing);
growableUniques.add(thing);
}
}
/**
* Casts to an ArrayList of unique values
* #return
*/
public List getList(){
return growableUniques;
}
public Object get(int index) {
return growableUniques.get(index);
}
public Object[] toObjectArray() {
int size = growableUniques.size();
returnable = new Object[size];
for (int i = 0; i < size; i++) {
returnable[i] = growableUniques.get(i);
}
return returnable;
}
}
I have a TestCollections class that looks like this:
package com.bprog.collections;
import com.bprog.out.Out;
/**
*
* #author Jonathan
*/
public class TestCollections {
public static void main(String[] args){
UniqueList ul = new UniqueList();
ul.add("Test");
ul.add("Test");
ul.add("Not a copy");
ul.add("Test");
//should only contain two things
Object[] content = ul.toObjectArray();
Out.pl("Array Content",content);
}
}
Works fine. All it does is it adds to a set if it does not have it already and there's an Arraylist that is returnable, as well as an object array.
Related
Getting my feet wet on RxJava. I have a class that implements Iterable I want to convert to an Observable. Using Observable.from() seems easy. However I need to setup and tear-down the code that provides me the individual entries (the next() in the iterator.
When I run through the entire sequence, that's easy. I added the call to the hasNext() function and when there is no next I run the teardown. However one of the very promising operators I want to use is take(someNumber). If the taking stops before the Iterator runs out of items, the cleanup code never runs.
What can I do to get my cleanup running? If using something else than from(Iterable), I'm OK with that. I'm stuck on Java6 for now. To illustrate my predicament I created a minimal sample:
Update: Based on feedback not to mix Iterator and Iterable together, I updated the code below. To understand the original answers, the original code is in that gist.
Updated Test code (still bad):
import rx.Observable;
import rx.functions.Action0;
import rx.functions.Action1;
/**
* #author stw
*
*/
public class RXTest {
/**
* #param args
*/
public static void main(String[] args) {
ComplicatedObject co = new ComplicatedObject();
Observable<FancyObject> fancy = Observable.from(co);
// if the take is less than the elements cleanup never
// runs. If you take the take out, cleanup runs
fancy.take(3).subscribe(
new Action1<FancyObject>() {
public void call(FancyObject item) {
System.out.println(item.getName());
}
},
new Action1<Throwable>() {
public void call(Throwable error) {
System.out.println("Error encountered: " + error.getMessage());
}
},
new Action0() {
public void call() {
System.out.println("Sequence complete");
}
}
);
}
}
The fancy object:
import java.util.Date;
import java.util.UUID;
/**
* #author stw
*
*/
public class FancyObject {
private String name = UUID.randomUUID().toString();
private Date created = new Date();
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreated() {
return this.created;
}
public void setCreated(Date created) {
this.created = created;
}
}
The iterator:
import java.util.Iterator;
/**
* #author stw
*
*/
public class FancyIterator implements Iterator<FancyObject> {
private final ComplicatedObject theObject;
private int fancyCount = 0;
public FancyIterator(ComplicatedObject co) {
this.theObject = co;
}
public boolean hasNext() {
return this.theObject.hasObject(this.fancyCount);
}
public FancyObject next() {
FancyObject result = this.theObject.getOne(this.fancyCount);
this.fancyCount++;
return result;
}
}
The Iterable:
import java.util.Iterator;
import java.util.Vector;
/**
* #author stw
*
*/
public class ComplicatedObject implements Iterable<FancyObject> {
private boolean isInitialized = false;
Vector<FancyObject> allOfThem = new Vector<FancyObject>();
public Iterator<FancyObject> iterator() {
return new FancyIterator(this);
}
public boolean hasObject(int whichone) {
if (!this.isInitialized) {
this.setupAccesstoFancyObject();
}
return (whichone < this.allOfThem.size());
}
public FancyObject getOne(int whichone) {
if (!this.isInitialized) {
this.setupAccesstoFancyObject();
}
if (whichone < this.allOfThem.size()) {
return this.allOfThem.get(whichone);
}
// If we ask bejond...
this.isInitialized = false;
this.teardownAccessToFancyObjects();
return null;
}
private void setupAccesstoFancyObject() {
System.out.println("Initializing fancy objects");
for (int i = 0; i < 20; i++) {
this.allOfThem.addElement(new FancyObject());
}
this.isInitialized = true;
}
private void teardownAccessToFancyObjects() {
System.out.println("I'm doing proper cleanup here");
}
}
But the real question (thx #Andreas) seem to be:
What construct can I use to create an Observable when the underlying code need setup/teardown, especially when one expects that not all elements are pulled. The Iterable just was my first idea
Update 2: Based on Dave's answer I created a gist with my working solution. The iterator isn't perfect, but it's a start.
Observable.using is used for tearing down on termination (completion or error) or unsubscription. To use it you need to make the tear-down code accessible so that your source observable can look like this:
source = Observable.using(
resourceFactory,
observableFactory,
resourceDisposer);
With your code it might look like this:
source = Observable.using(
() -> new ComplicatedObject(),
co -> Observable.from(co),
co -> co.tearDown());
If you want that kind of control you need to separate the implementation of Iterable from Iterator. Iterable means the class can provide an Iterator that is meaningful in whatever fashion makes sense for the class.
However, if you implement Iterator in the same class, then you are stuck with only ever having one Iterator for each instance of ComplicatedObject. The correct approach is to implement
class FancyObjectIterator implements Iterator<FancyObject>
{
...
}
separately from ComplicatedObject so you can merely discard the partially-used iterators when you are done with them. ComplicatedObject should implement only Iterable<FancyObject>.
If you object to that approach because the iterator has more state that needs special cleanup, then something is wrong with your design. The only state an Iterator should be aware of is the current position in the base "collection", for a very loose definition of "collection" and "position" since the concept of an iterator can apply to much more than typical collections.
You cannot implement Iterator and Iterable at the same time, since Iterable.iterator() must return a new Iterator or every call.
Code is allowed to iterate the same Iterable multiple times in parallel.
Example: An over-simplified way to find duplicate elements in an Iterable:
Iterable<MyObject> myIterable = ...;
for (MyObject myObj1 : myIterable) {
for (MyObject myObj2 : myIterable) {
if (myObj1 != myObj2 && myObj1.equals(myObj2)) {
// found duplicate
}
}
}
The enhanced for loops used here will each use an Iterator.
As you can see, each Iterator must maintain it's own independent position. Therefore, the iterator() method needs to return a new object, with it's own state.
And for your question on cleanup code, an Iterator does not have a close() method. Iterator state should not require cleanup. If they absolutely must, a finalizer can do it, but finalizers may take a very long time to be invoked. The general recommendation for finalizers is: DON'T.
So I have to make two methods:
void setUnique( boolean value)
boolean getUnique()
setUnique allows the client to set whether or not to allow duplicates( true means no duplicates, false means duplicates allowed,
getUnique is to return the current setting for unique
My assignment is I have to create a SortedIntList. java and a SortedIntListTest.java and I have to have these two methods included for when I test my list.
This is what I have so far and I already know its not correct as it has errors all over it:
public void setUnique(boolean value)
{
if(!list.contains(value))
{
list.add(value);
return index == true;
}
else
{
return index == false;
}
}
public boolean getUnique()
{
//return value ;
}
Now I've seen people use the hashset method. However we havnt learn that in class yet so it most likely wont be allowed to be used. I am stuck on this and would really like some help on another way of now allowing duplicates into the arraylist without using the hashset method
first of all above method public void setUnique(boolean value) it's return type is void but you are returning some boolean value whichis wrong.
now as per me your requirement there will be one boolean flag which indicate whether client wants duplicate values or not.
so in your class take one boolean variable "flag" and implement setter and getter for that variable. client will change that flag whenever he want to change.
now create one method which return List.
public List<Integer> getList(List<Integer> inputList){
List<Integer> list=new ArrayList<Integer>();
if(flag){
for(Intger i:inputList){
if(!list.contains(i)){
list.add(i);
}
}
}
else{
list=inputList;
}
return list;
}
You can write SortedIntList.java like this
public class SortedIntList {
private boolean isUnique;
private ArrayList<Integer> arrayList = new ArrayList<>();
public boolean isUnique() {
return isUnique;
}
public void setIsUnique(boolean isUnique) {
this.isUnique = isUnique;
}
public void addElement(int element){
//While inserting element, it will check whether isUnique is set or not
if(isUnique){
//If set, then it will check whether the list contains that element, if Yes, then skip it.
if(arrayList.contains(element)){
return;
}
}
arrayList.add(element);
}
// Add your custom methods for sorting purpose
public List getArray(){
return arrayList;
}
}
And SortedIntListTest.java like this
public class SortedIntListTest {
public static void main(String[] args) {
SortedIntList list = new SortedIntList();
list.setIsUnique(true);
list.addElement(10);
list.addElement(5);
list.addElement(10);
list.addElement(8);
System.out.println(list.getArray());
}
}
Based on the inputs, here is the template code to fill in. To find duplicates in array list, use contains method on list
public class SortedIntList<Integer> extends AbstractList<Integer>{
private List<Integer> myList = new LinkedList<Integer>
private boolean isunique;
public void add(int value){
Case 1: if duplicates are allowed
//add value to myList
Case 2: duplicates are not allowed
while adding you need to traverse the list if there is any such value
//sort the list
}
public void setUnique(boolean unique){
//set isUnique
//if value is changing from non-unique to unique
//traverse the list if there is any duplicate values remove them
}
public boolean isUnique(){
return isUnique;
}
}
I appologize for the title. I don't know what this computational problem is called.
I was hoping there was a collection class ready for me to use to solve this. I use TreeSet in the example bellow just to show what I need. I believe the example to be clear enough to explain the question.
public class MyClass
{
//I know TreeSet doesn't work. Is there a collection that would work like TreeSet
//but has a method similar to the imaginary overload of TreeSet.floor I invoke in my code?
private TreeSet<OrderElement<Integer, Object>> treeSet = new TreeSet<>();
//this method is irrelevant to the problem.
//it's here just for usability of this example class
public void addElement(int order, Object element)
{
treeSet.add(new OrderElement(order, element));
}
//this is the method I need to implement
public Object floor(int order)
{
//this overload does not exist. I need a collection with a similar function
return treeSet.floor(order);
}
}
//this class represents the elements in the TreeSet.
public class OrderElement<O extends Comparable, E>, implements Comparable<O>
{
public final O order;
public final E element;
public OrderElement(O order, E element)
{
this.order = order;
this.element = element;
}
#Override
public int compareTo(O param)
{
return this.order.compareTo(param);
}
#Override
public boolean equals(Object obj)
{
return obj.equals(this.order);
}
#Override
public int hashCode()
{
return this.order.hashCode();
}
}
You want to use TreeMap<Integer, Object> and your floor method is called floorKey there
http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html#floorKey(K)
I want to compare an array of comparables. The simplest way seems the following (details not shown):
public class ArrayComparable implements Comparable<ArrayComparable>{
ArrayList<Comparable<?>> list = new ArrayList<Comparable<?>>();
#Override
public int compareTo(ArrayComparable ac) {
Iterator<Comparable<?>> itr = ac.list.iterator();
for(Comparable<?> l : list) {
Comparable<?> itrNext = itr.next();
if(itrNext.getClass() == l.getClass()) {
if(itrNext.compareTo(l)) {
//something
} else {
//other stuff
}
} else {
//some other thing
}
}
}
Of course the problem here is that the compareTo as in itrNext.compareTo(l) will not work giving the error: The method compareTo(capture#6-of ?) in the type Comparable<capture#6-of ?> is not applicable for the arguments (Comparable<capture#7-of ?>)
which I understand why (as far as the method is concerned I might be comparing apples to oranges). On the other hand, I know I am not as I check for the class of things before comparing them.
So is there a way I can make this work? Don't worry about the sanity of comparing arrays of any comparables, as I have a good reason why I want to do that.
EDIT- SO why would I want to do something like this. Say I wanted to have an array of comparables, and I didn't care what was contained in each index, as long as the types corresponded, and they could be compared. Then I could do a general lexicographical compare between these arrays. This way I don't have to write a comparable for (int,int) and (int, string), and (string, double, string) or whatever you need. I just write one, and as long as I make sure that the types match (and I can), I am good to go.
Using the raw type Comparable wherever you're currently using Comparable<?> should work. Actually, you could just do that in one place if you want:
if (((Comparable) itrNext).compareTo(l) == 0)
Make ArrayComparable a generic class so that you can properly parameterize the generics rather than using <?> everywhere. Oh, and you might as well implement Iterable as well.
public class ArrayComparable<T> implements Comparable<ArrayComparable<T>>, Iterable<T>
{
List<Comparable<T>> list = new ArrayList<Comparable<T>>();
#Override
public int compareTo(ArrayComparable<T> ac)
{
// snip
}
#Override
public Iterator<T> iterator()
{
return list.iterator();
}
}
Try this:
if(itrNext.getClass().cast(itrNext).compareTo(l.getClass().cast(l))) {
//something
} else {
//other stuff
}
public class GenericDemo<T>{
T g;
public <T extends Comparable<T>> void printData(T a[]){
T max = a[0];
if(a[1].compareTo(max)>0){
max=a[1];
}
if(a[2].compareTo(max)>0){
max=a[1];
}
System.out.println(max);
System.out.println("DataType: " +a.getClass().getName());
}
public static void main(String[] ar)
{
Integer a[]={1,2,3};
Byte b[]= {4,6,7};
Short c[]={6,8,9};
GenericDemo g = new GenericDemo();
g.printData(a);
g.printData(b);
g.printData(c);
}
}
A good answer to this would be:
public final class ArrayComparable<T extends Comparable<T>>
implements Comparable<ArrayComparable<T>> {
private final ArrayList<T> list = new ArrayList<>();
#Override
public int compareTo(final ArrayComparable<T> other) {
final Iterator<T> it = other.list.iterator();
for (final T element : list) {
final T otherElement = it.next();
final int comparison = element.compareTo(otherElement);
if (comparison < 0) {
// something
} else if (comparison > 0) {
// other stuff
} else {
// other stuff
}
}
return 0;
}
}
The API for the Java Set interface states:
For example, some implementations prohibit null elements and some have restrictions on the types of their elements
I am looking for a basic Set implementation that does not require ordering (as ArrayList provides for the List interface) and that does not permit null. TreeSet, HashSet, and LinkedHashSet all allow null elements. Additionally, TreeSet has the requirement that elements implement Comparable.
It seems that no such basic Set exists currently. Does anyone know why? Or if one does exist where I can find it?
[Edit]: I do not want to allow nulls, because later in the code my class will iterate over all elements in the collection and call a specific method. (I'm actually using HashSet<MyRandomObject>). I would rather fail fast than fail later or accidentally incur some bizarre behavior due to a null being in the set.
Better than extending a particular implementation, you can easily write a proxy implementation of Set that checks for nulls. This analogous to Collections.checkedSet. Other than being applicable to any implementation, you can also be sure that you have overridden all applicable methods. Many flaws have been found by extending concrete collections which then have additional methods added in later versions.
I would say use composition instead of inheritance... it might be more work but it'll be more stable in the face of any changes that Sun might make to the Collections Framework.
public class NoNullSet<E> implements Set<E>
{
/** The set that is wrapped. */
final private Set<E> wrappedSet = new HashSet<E>();
public boolean add(E e)
{
if (e == null)
throw new IllegalArgumentException("You cannot add null to a NoNullSet");
return wrappedSet.add(e);
}
public boolean addAll(Collection<? extends E> c)
{
for (E e : c) add(e);
}
public void clear()
{ wrappedSet.clear(); }
public boolean contains(Object o)
{ return wrappedSet.contains(o); }
... wrap the rest of them ...
}
Note that this implementation does not depend on addAll calling add (which is an implementation detail and should not be used because it cannot be guaranteed to remain true in all Java releases).
There is no basic proprietary Set implementation that ignores or constrains null! There is EnumSet, but that one is tailors for the containment of enum types.
However, creating your own implementation can be avoided, if you use either Guava or Commons Collections:
1. Guava Solution:
Set noNulls = Constraints.constrainedSet(new HashSet(), Constraints.notNull());
2. Commons Collections:
Set noNulls = new HashSet();
CollectionUtils.addIgnoreNull(noNulls, object);
You could use apache collections and its PredicatedCollection class, and set the predicate to not allow nulls. You will get exceptions if someone sends nulls in.
This is a failry general purpose way of doing it - you provide a Filter implementation that can restrict what gets added in whatevber way you want. Take a look at the source for java.util.Collections for ideas on the wrapping (I think my implementaiton of the FilteredCollection class is correct... but it is not extensivly tested). There is a sample program at the end that shows the usage.
public interface Filter<T>
{
boolean accept(T item);
}
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
public class FilteredCollections
{
private FilteredCollections()
{
}
public static <T> Collection<T> filteredCollection(final Collection<T> c,
final Filter<T> filter)
{
return (new FilteredCollection<T>(c, filter));
}
private static class FilteredCollection<E>
implements Collection<E>,
Serializable
{
private final Collection<E> wrapped;
private final Filter<E> filter;
FilteredCollection(final Collection<E> collection, final Filter<E> f)
{
if(collection == null)
{
throw new IllegalArgumentException("collection cannot be null");
}
if(f == null)
{
throw new IllegalArgumentException("f cannot be null");
}
wrapped = collection;
filter = f;
}
public int size()
{
return (wrapped.size());
}
public boolean isEmpty()
{
return (wrapped.isEmpty());
}
public boolean contains(final Object o)
{
return (wrapped.contains(o));
}
public Iterator<E> iterator()
{
return new Iterator<E>()
{
final Iterator<? extends E> i = wrapped.iterator();
public boolean hasNext()
{
return (i.hasNext());
}
public E next()
{
return (i.next());
}
public void remove()
{
i.remove();
}
};
}
public Object[] toArray()
{
return (wrapped.toArray());
}
public <T> T[] toArray(final T[] a)
{
return (wrapped.toArray(a));
}
public boolean add(final E e)
{
final boolean ret;
if(filter.accept(e))
{
ret = wrapped.add(e);
}
else
{
// you could throw an exception instead if you want -
// IllegalArgumentException is what I would suggest
ret = false;
}
return (ret);
}
public boolean remove(final Object o)
{
return (wrapped.remove(o));
}
public boolean containsAll(final Collection<?> c)
{
return (wrapped.containsAll(c));
}
public boolean addAll(final Collection<? extends E> c)
{
final E[] a;
boolean result;
a = (E[])wrapped.toArray();
result = false;
for(final E e : a)
{
result |= wrapped.add(e);
}
return result;
}
public boolean removeAll(final Collection<?> c)
{
return (wrapped.removeAll(c));
}
public boolean retainAll(final Collection<?> c)
{
return (wrapped.retainAll(c));
}
public void clear()
{
wrapped.clear();
}
public String toString()
{
return (wrapped.toString());
}
}
}
import java.util.ArrayList;
import java.util.Collection;
public class Main
{
private static class NullFilter<T>
implements Filter<T>
{
public boolean accept(final T item)
{
return (item != null);
}
}
public static void main(final String[] argv)
{
final Collection<String> strings;
strings = FilteredCollections.filteredCollection(new ArrayList<String>(),
new NullFilter<String>());
strings.add("hello");
strings.add(null);
strings.add("world");
if(strings.size() != 2)
{
System.err.println("ERROR: strings.size() == " + strings.size());
}
System.out.println(strings);
}
}
Yes -- in the docs for com.google.common.collect.ImmutableSet:
A high-performance, immutable Set with reliable, user-specified iteration order. Does not permit null elements.
You could easily write your own, by subclassing an appropriate existing class, and overriding all relevant methods so that you can't add null elements.
You may also wish to check out Google Collections. They are more null phobic, I believe.
for me, I didn't find one,
so I overrode the add function
Collection<String> errors = new HashSet<String>() {
#Override
public boolean add(String s) {
return StringUtil.hasContent(s) && super.add(s);//we don't want add null and we allow HashSet.add(null)
}
};
[Edit]: I do not want to allow nulls, because later in the code my
class will iterate over all elements in the collection and call a
specific method.
Instead of checking null, every time, we can simply remove the null once before iterating over the set.
You can remove the null values using set.remove(null);
Set<String> set = new HashSet<>();
set.add("test");
set.add(null);
set.add(null);
System.out.println(set);
set.remove(null);
System.out.println(set);
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
Output
[null, test]
[test]
test
BTW, if you'd asked for a Map implementation that does not allow nulls, the old java.util.Hashtable does not.
In this particular question/example surely if you have a HashSet<MyRandomObject> mySet call mySet.remove(null) before starting the iteration over all elements you mentioned?
I am not sure of a type which this is true. But could you not inherit from a collection or HashTable of your choice and override the Add method, throwing an exception if the element is null?
Why do you not want to allow null?
Do you want to throw an exception if null is added to your set? If so, just do something like this:
private Set<Object> mySet = new HashSet<Object>() {
#Override
public boolean add(Object e) {
if (e == null)
throw new IllegalArgumentException("null"); // or NPE
// or, of course, you could just return false
return super.add(e);
}
};
HashSet's addAll() calls add() repeatedly, so this is the only method you'd have to override.
Hashtable does not allow null values......