Tengo un ArrayList<String>
, y quiero eliminar cadenas repetidas de él. ¿Cómo puedo hacer esto?
Tengo un ArrayList<String>
, y quiero eliminar cadenas repetidas de él. ¿Cómo puedo hacer esto?
Respuestas:
Si no desea duplicados en un Collection
, debe considerar por qué está utilizando un Collection
que permite duplicados. La forma más fácil de eliminar elementos repetidos es agregar el contenido a Set
(que no permitirá duplicados) y luego agregar la parte Set
posterior a ArrayList
:
Set<String> set = new HashSet<>(yourList);
yourList.clear();
yourList.addAll(set);
Por supuesto, esto destruye el orden de los elementos en el ArrayList
.
public Set<Object> findDuplicates(List<Object> list) { Set<Object> items = new HashSet<Object>(); Set<Object> duplicates = new HashSet<Object>(); for (Object item : list) { if (items.contains(item)) { duplicates.add(item); } else { items.add(item); } } return duplicates; }
List
y Set
(en lugar de los tipos de implementación ArrayList
y HashSet
como en su ejemplo).
new HashSet(al)
lugar de inicializarlo para vaciarlo y llamarlo addAll
.
Object
tiene varios valores si dos de ellos se repiten, los considero duplicados (otros valores pueden ser diferentes) y uso Set
.
Si bien la conversión ArrayList
a a HashSet
elimina eficazmente los duplicados, si necesita preservar el orden de inserción, prefiero sugerirle que use esta variante
// list is some List of Strings
Set<String> s = new LinkedHashSet<>(list);
Luego, si necesita recuperar una List
referencia, puede usar nuevamente el constructor de conversión.
En Java 8:
List<String> deduped = list.stream().distinct().collect(Collectors.toList());
Tenga en cuenta que el contrato hashCode-equals para los miembros de la lista debe respetarse para que el filtrado funcione correctamente.
addAll
hacerlo new TreeSet<String>(String.CASE_INSENSITIVE_ORDER)
. El primer elemento agregado permanecerá en el conjunto, por lo que si su lista contiene "Perro" y "perro" (en ese orden) TreeSet
, contendrá "Perro". Si se debe preservar el orden, antes de la línea de la respuesta list.replaceAll(String::toUpperCase);
.
Supongamos que tenemos una lista de me String
gusta:
List<String> strList = new ArrayList<>(5);
// insert up to five items to list.
Entonces podemos eliminar elementos duplicados de múltiples maneras.
List<String> deDupStringList = new ArrayList<>(new HashSet<>(strList));
Nota: Si queremos mantener el orden de inserción, entonces debemos usarLinkedHashSet
en lugar deHashSet
List<String> deDupStringList2 = Lists.newArrayList(Sets.newHashSet(strList));
List<String> deDupStringList3 = strList.stream().distinct().collect(Collectors.toList());
Nota: En caso de que queramos recopilar el resultado en una implementación de lista específica, por ejemplo LinkedList
, podemos modificar el ejemplo anterior como:
List<String> deDupStringList3 = strList.stream().distinct()
.collect(Collectors.toCollection(LinkedList::new));
También podemos usarlo parallelStream
en el código anterior, pero es posible que no proporcione los beneficios de rendimiento esperados. Mira esta pregunta para más.
parallel streams
siempre obtendría un mejor rendimiento. Pero es un mito. Más tarde aprendí que hay ciertos escenarios en los que deberían usarse flujos paralelos. En este escenario, las secuencias paralelas no ofrecerán un mejor rendimiento. y sí, las secuencias paralelas pueden no dar los resultados deseados en algunos casos. List<String> deDupStringList3 = stringList.stream().map(String::toLowerCase).distinct().collect(Collectors.toList());
debería ser la solución adecuada en este caso
Si no quieres duplicados, usa un Set en lugar de a List
. Para convertir a List
a Set
puede usar el siguiente código:
// list is some List of Strings
Set<String> s = new HashSet<String>(list);
Si es realmente necesario, puede usar la misma construcción para convertir un Set
respaldo en a List
.
Set
no se puede usar aquí.
También puede hacerlo de esta manera y preservar el orden:
// delete duplicates (if any) from 'myArrayList'
myArrayList = new ArrayList<String>(new LinkedHashSet<String>(myArrayList));
Las secuencias Java 8 proporcionan una forma muy simple de eliminar elementos duplicados de una lista. Usando el método distinto. Si tenemos una lista de ciudades y queremos eliminar duplicados de esa lista, se puede hacer en una sola línea:
List<String> cityList = new ArrayList<>();
cityList.add("Delhi");
cityList.add("Mumbai");
cityList.add("Bangalore");
cityList.add("Chennai");
cityList.add("Kolkata");
cityList.add("Mumbai");
cityList = cityList.stream().distinct().collect(Collectors.toList());
Aquí hay una manera que no afecta el orden de su lista:
ArrayList l1 = new ArrayList();
ArrayList l2 = new ArrayList();
Iterator iterator = l1.iterator();
while (iterator.hasNext()) {
YourClass o = (YourClass) iterator.next();
if(!l2.contains(o)) l2.add(o);
}
l1 es la lista original, y l2 es la lista sin elementos repetidos (asegúrese de que YourClass tenga el método de igualdad de acuerdo con lo que desea representar para la igualdad)
ArrayList<T>
deben usarse en lugar de ArrayList
) 2) La creación explícita de iteradores puede evitarse usando a for (T current : l1) { ... }
. Incluso si quisieras usar Iterator
explícitamente, iterador
está mal escrito.
Es posible eliminar duplicados de la lista de arrays sin usar HashSet o una lista de arrays más .
Prueba este código ...
ArrayList<String> lst = new ArrayList<String>();
lst.add("ABC");
lst.add("ABC");
lst.add("ABCD");
lst.add("ABCD");
lst.add("ABCE");
System.out.println("Duplicates List "+lst);
Object[] st = lst.toArray();
for (Object s : st) {
if (lst.indexOf(s) != lst.lastIndexOf(s)) {
lst.remove(lst.lastIndexOf(s));
}
}
System.out.println("Distinct List "+lst);
La salida es
Duplicates List [ABC, ABC, ABCD, ABCD, ABCE]
Distinct List [ABC, ABCD, ABCE]
ImmutableSet.copyOf(lst).toList()
.
indexOf
itera lst
utilizando un bucle for.
También hay ImmutableSet
de guayaba como opción ( aquí está la documentación):
ImmutableSet.copyOf(list);
ImmutableSet.asList()
método, devolviendo un ImmutableList
, si lo necesita de nuevo como a List
.
Esto puede resolver el problema:
private List<SomeClass> clearListFromDuplicateFirstName(List<SomeClass> list1) {
Map<String, SomeClass> cleanMap = new LinkedHashMap<String, SomeClass>();
for (int i = 0; i < list1.size(); i++) {
cleanMap.put(list1.get(i).getFirstName(), list1.get(i));
}
List<SomeClass> list = new ArrayList<SomeClass>(cleanMap.values());
return list;
}
Probablemente un poco exagerado, pero disfruto este tipo de problema aislado. :)
Este código utiliza un conjunto temporal (para la verificación de unicidad) pero elimina elementos directamente dentro de la lista original. Dado que la eliminación de elementos dentro de una ArrayList puede inducir una gran cantidad de copia de matriz, se evita el método remove (int).
public static <T> void removeDuplicates(ArrayList<T> list) {
int size = list.size();
int out = 0;
{
final Set<T> encountered = new HashSet<T>();
for (int in = 0; in < size; in++) {
final T t = list.get(in);
final boolean first = encountered.add(t);
if (first) {
list.set(out++, t);
}
}
}
while (out < size) {
list.remove(--size);
}
}
Mientras estamos en ello, aquí hay una versión para LinkedList (¡mucho mejor!):
public static <T> void removeDuplicates(LinkedList<T> list) {
final Set<T> encountered = new HashSet<T>();
for (Iterator<T> iter = list.iterator(); iter.hasNext(); ) {
final T t = iter.next();
final boolean first = encountered.add(t);
if (!first) {
iter.remove();
}
}
}
Use la interfaz de marcador para presentar una solución unificada para List:
public static <T> void removeDuplicates(List<T> list) {
if (list instanceof RandomAccess) {
// use first version here
} else {
// use other version here
}
}
EDITAR: Supongo que las cosas genéricas realmente no agregan ningún valor aquí ... Oh, bueno. :)
public static void main(String[] args){
ArrayList<Object> al = new ArrayList<Object>();
al.add("abc");
al.add('a');
al.add('b');
al.add('a');
al.add("abc");
al.add(10.3);
al.add('c');
al.add(10);
al.add("abc");
al.add(10);
System.out.println("Before Duplicate Remove:"+al);
for(int i=0;i<al.size();i++){
for(int j=i+1;j<al.size();j++){
if(al.get(i).equals(al.get(j))){
al.remove(j);
j--;
}
}
}
System.out.println("After Removing duplicate:"+al);
}
Si está dispuesto a usar una biblioteca de terceros, puede usar el método distinct()
en Eclipse Collections (anteriormente GS Collections).
ListIterable<Integer> integers = FastList.newListWith(1, 3, 1, 2, 2, 1);
Assert.assertEquals(
FastList.newListWith(1, 3, 2),
integers.distinct());
La ventaja de usar en distinct()
lugar de convertir a un Conjunto y luego volver a una Lista es que distinct()
conserva el orden de la Lista original, conservando la primera aparición de cada elemento. Se implementa mediante el uso de un conjunto y una lista.
MutableSet<T> seenSoFar = UnifiedSet.newSet();
int size = list.size();
for (int i = 0; i < size; i++)
{
T item = list.get(i);
if (seenSoFar.add(item))
{
targetCollection.add(item);
}
}
return targetCollection;
Si no puede convertir su Lista original en un tipo de Colecciones de Eclipse, puede usar ListAdapter para obtener la misma API.
MutableList<Integer> distinct = ListAdapter.adapt(integers).distinct();
Nota: Soy un committer para Eclipse Collections.
Estas tres líneas de código pueden eliminar el elemento duplicado de ArrayList o de cualquier colección.
List<Entity> entities = repository.findByUserId(userId);
Set<Entity> s = new LinkedHashSet<Entity>(entities);
entities.clear();
entities.addAll(s);
Cuando esté completando ArrayList, use una condición para cada elemento. Por ejemplo:
ArrayList< Integer > al = new ArrayList< Integer >();
// fill 1
for ( int i = 0; i <= 5; i++ )
if ( !al.contains( i ) )
al.add( i );
// fill 2
for (int i = 0; i <= 10; i++ )
if ( !al.contains( i ) )
al.add( i );
for( Integer i: al )
{
System.out.print( i + " ");
}
Obtendremos una matriz {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Si desea conservar su pedido, lo mejor es utilizar LinkedHashSet . Porque si desea pasar esta lista a una consulta de inserción al iterarla, el orden se conservará.
Prueba esto
LinkedHashSet link=new LinkedHashSet();
List listOfValues=new ArrayList();
listOfValues.add(link);
Esta conversión será muy útil cuando desee devolver una Lista pero no un Conjunto.
Código:
List<String> duplicatList = new ArrayList<String>();
duplicatList = Arrays.asList("AA","BB","CC","DD","DD","EE","AA","FF");
//above AA and DD are duplicate
Set<String> uniqueList = new HashSet<String>(duplicatList);
duplicatList = new ArrayList<String>(uniqueList); //let GC will doing free memory
System.out.println("Removed Duplicate : "+duplicatList);
Nota: Definitivamente, habrá sobrecarga de memoria.
ArrayList<String> city=new ArrayList<String>();
city.add("rajkot");
city.add("gondal");
city.add("rajkot");
city.add("gova");
city.add("baroda");
city.add("morbi");
city.add("gova");
HashSet<String> hashSet = new HashSet<String>();
hashSet.addAll(city);
city.clear();
city.addAll(hashSet);
Toast.makeText(getActivity(),"" + city.toString(),Toast.LENGTH_SHORT).show();
LinkedHashSet hará el truco.
String[] arr2 = {"5","1","2","3","3","4","1","2"};
Set<String> set = new LinkedHashSet<String>(Arrays.asList(arr2));
for(String s1 : set)
System.out.println(s1);
System.out.println( "------------------------" );
String[] arr3 = set.toArray(new String[0]);
for(int i = 0; i < arr3.length; i++)
System.out.println(arr3[i].toString());
// salida: 5,1,2,3,4
List<String> result = new ArrayList<String>();
Set<String> set = new LinkedHashSet<String>();
String s = "ravi is a good!boy. But ravi is very nasty fellow.";
StringTokenizer st = new StringTokenizer(s, " ,. ,!");
while (st.hasMoreTokens()) {
result.add(st.nextToken());
}
System.out.println(result);
set.addAll(result);
result.clear();
result.addAll(set);
System.out.println(result);
output:
[ravi, is, a, good, boy, But, ravi, is, very, nasty, fellow]
[ravi, is, a, good, boy, But, very, nasty, fellow]
Esto se usa para su lista de objetos personalizados
public List<Contact> removeDuplicates(List<Contact> list) {
// Set set1 = new LinkedHashSet(list);
Set set = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (((Contact) o1).getId().equalsIgnoreCase(((Contact) o2).getId()) /*&&
((Contact)o1).getName().equalsIgnoreCase(((Contact)o2).getName())*/) {
return 0;
}
return 1;
}
});
set.addAll(list);
final List newList = new ArrayList(set);
return newList;
}
puede usar el bucle anidado de la siguiente manera:
ArrayList<Class1> l1 = new ArrayList<Class1>();
ArrayList<Class1> l2 = new ArrayList<Class1>();
Iterator iterator1 = l1.iterator();
boolean repeated = false;
while (iterator1.hasNext())
{
Class1 c1 = (Class1) iterator1.next();
for (Class1 _c: l2) {
if(_c.getId() == c1.getId())
repeated = true;
}
if(!repeated)
l2.add(c1);
}
Aquí está mi código sin usar ninguna otra estructura de datos como set o hashmap
for (int i = 0; i < Models.size(); i++){
for (int j = i + 1; j < Models.size(); j++) {
if (Models.get(i).getName().equals(Models.get(j).getName())) {
Models.remove(j);
j--;
}
}
}
ArrayList<String> list = new ArrayList<String>();
HashSet<String> unique = new LinkedHashSet<String>();
HashSet<String> dup = new LinkedHashSet<String>();
boolean b = false;
list.add("Hello");
list.add("Hello");
list.add("how");
list.add("are");
list.add("u");
list.add("u");
for(Iterator iterator= list.iterator();iterator.hasNext();)
{
String value = (String)iterator.next();
System.out.println(value);
if(b==unique.add(value))
dup.add(value);
else
unique.add(value);
}
System.out.println(unique);
System.out.println(dup);
Si desea eliminar duplicados de ArrayList significa encontrar la siguiente lógica,
public static Object[] removeDuplicate(Object[] inputArray)
{
long startTime = System.nanoTime();
int totalSize = inputArray.length;
Object[] resultArray = new Object[totalSize];
int newSize = 0;
for(int i=0; i<totalSize; i++)
{
Object value = inputArray[i];
if(value == null)
{
continue;
}
for(int j=i+1; j<totalSize; j++)
{
if(value.equals(inputArray[j]))
{
inputArray[j] = null;
}
}
resultArray[newSize++] = value;
}
long endTime = System.nanoTime()-startTime;
System.out.println("Total Time-B:"+endTime);
return resultArray;
}