Is there a no-duplicate List implementation out there?

后端 未结 11 644
悲哀的现实
悲哀的现实 2020-11-29 00:53

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 e

相关标签:
11条回答
  • 2020-11-29 00:56

    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>.

    0 讨论(0)
  • 2020-11-29 00:56

    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.

    0 讨论(0)
  • 2020-11-29 00:57

    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);
            }
        }
    }   
    
    0 讨论(0)
  • 2020-11-29 00:57

    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 ;-)

    0 讨论(0)
  • 2020-11-29 01:07

    You should seriously consider dhiller's answer:

    1. 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.
    2. 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.

    0 讨论(0)
  • 2020-11-29 01:07

    NOTE: it does not take subList implementation into account.

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.HashSet;
    import java.util.Set;
    
    public class UniqueList<T> extends ArrayList<T> {
    
        private static final long serialVersionUID = 1L;
    
        /** Unique elements SET */
        private final Set<T> set=new HashSet();
    
        /** Used by addAll methods */
        private Collection<T> addUnique(Collection<? extends T> col) {
            Collection<T> unique=new ArrayList();
            for(T e: col){
                if (set.add(e)) unique.add(e);
            }
            return unique;
        }
    
        @Override
        public boolean add(T e) {
            return set.add(e) ? super.add(e) : false;
        }
    
        @Override
        public boolean addAll(Collection<? extends T> col) {
            return super.addAll(addUnique(col));
        }
    
        @Override
        public void add(int index, T e) {
            if (set.add(e)) super.add(index, e);
        }
    
        @Override
        public boolean addAll(int index, Collection<? extends T> col) {
            return super.addAll(index, addUnique(col));
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题