Pregunta

Yo sé acerca de SortedSet, pero en mi caso necesito algo que implementa List, y no Set.Entonces, ¿hay una aplicación por ahí, en la API o en otro lugar?

No debería ser difícil de aplicar a mí mismo, pero pensé, ¿por qué no pedir a la gente aquí en primer lugar?

¿Fue útil?

Solución

No hay una colección Java en la biblioteca estándar para hacer esto. LinkedHashSet<E> conserva el pedido de forma similar a un < =>, sin embargo, así que si ajusta su conjunto en un List cuando quiere usarlo como commons-collections4 obtendrá la semántica que desea.

Alternativamente, las Commons Collections (o SetUniqueList, para la versión genérica ) tiene un SetUniqueList<E> que ya hace lo que quiere: <=> / <=> .

Otros consejos

Aquí es lo que yo hice y funciona.

Suponiendo que tengo una ArrayList para trabajar con la primera cosa que hice fue creado un nuevo LinkedHashMap.

LinkedHashSet<E> hashSet = new LinkedHashSet<E>()

Entonces yo intento agregar mi nuevo elemento a la LinkedHashSet.El método add de no alterar el LinkedHasSet y devuelve false si el elemento nuevo que es un duplicado.Así que esto se convierte en una condición para que yo pueda probar antes de añadir a la ArrayList.

if (hashSet.add(E)) arrayList.add(E);

Este es un sencillo y elegante manera de evitar los duplicados de ser agregado a una lista de matrices.Si lo desea, puede encapsular y sobreescribir el método add en una clase que extiende la ArrayList.Sólo recuerde que lidiar con addAll con un bucle a través de los elementos y se llama al método add.

Entonces esto es lo que hice eventualmente. Espero que esto ayude a alguien más.

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

Debería considerar seriamente la respuesta de dhiller:

  1. En lugar de preocuparse por agregar sus objetos a una Lista sin duplicados, agréguelos a un Conjunto (cualquier implementación), que por naturaleza filtrará los duplicados.
  2. Cuando necesite llamar al método que requiere una Lista, envuélvala en un new ArrayList(set) (o un new LinkedList(set), lo que sea).

Creo que la solución que publicó con el NoDuplicatesList tiene algunos problemas, principalmente con el método contains(), además de que su clase no maneja la búsqueda de duplicados en la Colección pasada a su método addAll().

¿Por qué no encapsular un conjunto con una lista, ordenar como:

new ArrayList( new LinkedHashSet() )

Esto deja la otra implementación para alguien que es un verdadero maestro de Colecciones ;-)

Necesitaba algo así, así que fui a las colecciones comunes y utilicé la SetUniqueList, pero cuando ejecuté alguna prueba de rendimiento, descubrí que no parece optimizado en comparación con el caso si quiero usar un Set y obtener un Array utilizando el método Set.toArray (), SetUniqueTest tardó 20: 1 en completarse y luego atravesar 100,000 cadenas en comparación con la otra implementación, lo cual es una gran diferencia, por lo que si le preocupa el rendimiento, le recomiendo que use el Set y obtenga una matriz en lugar de usar SetUniqueList, a menos que realmente necesite la lógica de SetUniqueList, entonces necesita verificar otras soluciones ...

El método principal del código de prueba:

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

}

Saludos Mohammed Sleem http://abusleem.net/blog

NOTA: no tiene en cuenta la implementación de subList .

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

}

La documentación para interfaces de recopilación dice:

  

Establecer & # 8212; una colección que no puede contener elementos duplicados.
  Lista & # 8212; Una colección ordenada (a veces llamada secuencia). Las listas pueden contener elementos duplicados.

Entonces, si no quieres duplicados, probablemente no deberías usar una lista.

en el método add, ¿por qué no usar HashSet.add() para verificar duplicados en lugar de HashSet.consist(). true devolverá false si no hay duplicados y <=> lo contrario.

La parte superior de mi cabeza, listas de permitir duplicados.Usted podría implementar rápidamente una UniqueArrayList y se anulan todas las add / insert funciones para comprobar contains() antes de llamar a los métodos heredados.Para uso personal, sólo se puede aplicar el add el método que use, y reemplazar los demás para lanzar una excepción en el caso de los futuros programadores de intentar utilizar la lista de una manera diferente.

Acabo de crear mi propia UniqueList en mi pequeña biblioteca como esta:

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

Tengo una clase TestCollections que se ve así:

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

Funciona bien. Todo lo que hace es agregar a un conjunto si aún no lo tiene y hay una Arraylist que es retornable, así como una matriz de objetos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top