Risposte:
Se non si desidera duplicati in a Collection
, è necessario considerare il motivo per cui si sta utilizzando un Collection
duplicato che consente duplicati. Il modo più semplice per rimuovere elementi ripetuti è aggiungere il contenuto a un Set
(che non consentirà duplicati) e quindi aggiungere il Set
ritorno a ArrayList
:
Set<String> set = new HashSet<>(yourList);
yourList.clear();
yourList.addAll(set);
Naturalmente, questo distrugge l'ordinamento degli elementi nel 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
e Set
(invece dei tipi di implementazione ArrayList
e HashSet
come nel tuo esempio).
new HashSet(al)
invece di inizializzarlo su vuoto e chiamando addAll
.
Object
ha diversi valori se due di essi si ripetono li considero duplicati (altri valori possono essere diversi) e uso Set
?
Sebbene la conversione ArrayList
in una HashSet
rimuova efficacemente i duplicati, se è necessario preservare l'ordine di inserzione, preferirei suggerire di utilizzare questa variante
// list is some List of Strings
Set<String> s = new LinkedHashSet<>(list);
Quindi, se è necessario recuperare un List
riferimento, è possibile utilizzare nuovamente il costruttore della conversione.
In Java 8:
List<String> deduped = list.stream().distinct().collect(Collectors.toList());
Si noti che il contratto hashCode-equals per i membri dell'elenco deve essere rispettato affinché il filtro funzioni correttamente.
addAll
a new TreeSet<String>(String.CASE_INSENSITIVE_ORDER)
. Il primo elemento aggiunto rimarrà nel set, quindi se la tua lista contiene "Cane" e "cane" (in quell'ordine) TreeSet
conterrà "Cane". Se l'ordine deve essere preservato, prima della riga nella risposta inserita list.replaceAll(String::toUpperCase);
.
Supponiamo di avere un elenco di String
come:
List<String> strList = new ArrayList<>(5);
// insert up to five items to list.
Quindi possiamo rimuovere elementi duplicati in più modi.
List<String> deDupStringList = new ArrayList<>(new HashSet<>(strList));
Nota: se vogliamo mantenere l'ordine di inserimento, dobbiamo usarlo LinkedHashSet
al posto diHashSet
List<String> deDupStringList2 = Lists.newArrayList(Sets.newHashSet(strList));
List<String> deDupStringList3 = strList.stream().distinct().collect(Collectors.toList());
Nota: nel caso in cui desideriamo raccogliere il risultato in una specifica implementazione dell'elenco ad esempio LinkedList
, possiamo modificare l'esempio sopra come:
List<String> deDupStringList3 = strList.stream().distinct()
.collect(Collectors.toCollection(LinkedList::new));
Possiamo usare parallelStream
anche nel codice sopra, ma potrebbe non dare benefici prestazionali previsti. Controlla questa domanda per ulteriori informazioni.
parallel streams
darà sempre prestazioni migliori. Ma è un mito. In seguito ho appreso che ci sono alcuni scenari in cui si dovrebbero usare flussi paralleli. In questo scenario i flussi paralleli non forniranno prestazioni migliori. e sì, flussi paralleli potrebbero non dare alcuni risultati desiderati. List<String> deDupStringList3 = stringList.stream().map(String::toLowerCase).distinct().collect(Collectors.toList());
dovrebbe essere la soluzione adatta in questo caso
Se non vuoi duplicati, usa un Set invece di a List
. Per convertire a List
in a Set
puoi usare il seguente codice:
// list is some List of Strings
Set<String> s = new HashSet<String>(list);
Se veramente necessario, puoi usare la stessa costruzione per convertire un Set
dorso in a List
.
Set
non può essere usato qui.
Puoi anche farlo in questo modo e conservare l'ordine:
// delete duplicates (if any) from 'myArrayList'
myArrayList = new ArrayList<String>(new LinkedHashSet<String>(myArrayList));
I flussi Java 8 forniscono un modo molto semplice per rimuovere elementi duplicati da un elenco. Utilizzando il metodo distinto. Se abbiamo un elenco di città e vogliamo rimuovere i duplicati da tale elenco, è possibile farlo in un'unica riga:
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());
Ecco un modo che non influisce sull'ordinamento della tua 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 è l'elenco originale e l2 è l'elenco senza elementi ripetuti (assicurarsi che YourClass abbia il metodo equals in base a ciò che si desidera rappresentare per l'uguaglianza)
ArrayList<T>
dovrebbe essere usato al posto di ArrayList
) 2) La creazione esplicita di iteratori può essere evitata usando a for (T current : l1) { ... }
. Anche se volevi usare Iterator
esplicitamente, iterador
è scritto male.
È possibile rimuovere i duplicati dall'arraylist senza utilizzare HashSet o un altro arraylist .
Prova questo codice ..
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);
L'output è
Duplicates List [ABC, ABC, ABCD, ABCD, ABCE]
Distinct List [ABC, ABCD, ABCE]
ImmutableSet.copyOf(lst).toList()
.
indexOf
itera l' lst
utilizzo di un ciclo for.
C'è anche ImmutableSet
da Guava come opzione ( ecco la documentazione):
ImmutableSet.copyOf(list);
ImmutableSet.asList()
metodo, che restituisce un ImmutableList
, se è necessario ripristinarlo come a List
.
questo può risolvere il 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;
}
Probabilmente un po 'eccessivo, ma mi piace questo tipo di problema isolato. :)
Questo codice utilizza un set temporaneo (per il controllo dell'unicità) ma rimuove gli elementi direttamente dall'elenco originale. Poiché la rimozione degli elementi all'interno di un ArrayList può indurre un'enorme quantità di copie degli array, si evita il metodo 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);
}
}
Mentre ci siamo, ecco una versione per LinkedList (molto più bella!):
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();
}
}
}
Utilizzare l'interfaccia marcatore per presentare una soluzione unificata per Elenco:
public static <T> void removeDuplicates(List<T> list) {
if (list instanceof RandomAccess) {
// use first version here
} else {
// use other version here
}
}
EDIT: Immagino che la roba generica non aggiunga davvero alcun valore qui .. Oh bene. :)
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);
}
Se si desidera utilizzare una libreria di terze parti, è possibile utilizzare il metodo distinct()
nelle raccolte Eclipse (precedentemente raccolte GS).
ListIterable<Integer> integers = FastList.newListWith(1, 3, 1, 2, 2, 1);
Assert.assertEquals(
FastList.newListWith(1, 3, 2),
integers.distinct());
Il vantaggio di utilizzare distinct()
invece di convertire in un set e poi di nuovo in un elenco è quello di distinct()
preservare l'ordine dell'elenco originale, mantenendo la prima occorrenza di ciascun elemento. È implementato utilizzando sia un set che un elenco.
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;
Se non riesci a convertire il tuo Elenco originale in un tipo di raccolte Eclipse, puoi utilizzare ListAdapter per ottenere la stessa API.
MutableList<Integer> distinct = ListAdapter.adapt(integers).distinct();
Nota: sono un committer per le raccolte Eclipse.
Queste tre righe di codice possono rimuovere l'elemento duplicato da ArrayList o da qualsiasi raccolta.
List<Entity> entities = repository.findByUserId(userId);
Set<Entity> s = new LinkedHashSet<Entity>(entities);
entities.clear();
entities.addAll(s);
Quando si riempie l'ArrayList, utilizzare una condizione per ciascun elemento. Per esempio:
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 + " ");
}
Otterremo un array {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Se vuoi conservare il tuo ordine, allora è meglio usare LinkedHashSet . Perché se si desidera passare questo elenco a una query di inserimento mediante iterazione, l'ordine verrà conservato.
Prova questo
LinkedHashSet link=new LinkedHashSet();
List listOfValues=new ArrayList();
listOfValues.add(link);
Questa conversione sarà molto utile quando si desidera restituire un elenco ma non un set.
Codice:
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: sicuramente ci sarà un sovraccarico di 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 farà il trucco.
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());
// output: 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]
Questo è usato per il tuo elenco di oggetti personalizzati
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;
}
puoi usare il ciclo nidificato nel seguente modo:
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);
}
Come detto prima, dovresti usare una classe che implementa l'interfaccia Set invece di Elenco per essere sicuro dell'unicità degli elementi. Se è necessario mantenere l'ordine degli elementi, è possibile utilizzare l'interfaccia SortedSet; la classe TreeSet implementa tale interfaccia.
Ecco il mio codice senza usare altre strutture di dati come 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);
Se desideri rimuovere i duplicati da ArrayList significa trovare la logica di seguito,
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;
}