2010-12-01 20 views
6

ArrayLst ile arama yapmak ve aynı olan tüm girdileri silmek istiyorum. ÖrneğinJava'da bir ArrayList'in değiştirilmesi

benim liste olsaydı: elma, portakal, muz, armut, şeftali, portakal,

ardından "turuncu" silinmiş olacaktır (her iki KADINKIZ).

safça, denedim: Ben kelimeyi eşitse (lastIndexOf (userword)) .remove nasıl yazdı

for(String word : userlist){ 

for(String otherword : userlist){ 

... 
} 
} 

ve onların endeksleri farklıdır.

Bu durum, istisnadan sonra istisnalara yol açmıştı ve bir liste üzerinde çalışırken, herşeyi yanlış yapan bir listeyi manipüle ettiğimi çabucak farkettim.

Yani
ArrayList<String> copylist = userlist; 

for(String word : copylist){ 

    for(String otherword : copylist){ 

    if(word.equalsIgnoreCase(otherword) 
      && copylist.lastIndexOf(word)!=copylist.lastIndexOf(otherword)){ 

userlist.remove(userlist.lastIndexOf(word)); 
userlist.remove(userlist.lastIndexOf(otherword)); 
    } 

    } 
    } 

SO bunu denedim listenin bir kopyasını yapmaya karar verdi ve bu benzer sorunlar vardı. Özellikle ConcurrentModificationException. Yerine geçtikten sonra, kafamda ne oldukça kolay bir süreç olmalı, Java'da çalışmam mümkün değil. Lütfen yardım et.

cevap

10

Şu anda listenin bir kopyasını oluşturmuyorsunuz. Aynı listeye referans veren yeni bir değişken açıklıyorsunuz. listenin bir kopyasını yapmak için kullanın:

ArrayList<String> copyList = new ArrayList<String>(userList); 

Ancak, ben farklı bir yaklaşım öneririm:

ArrayList<String> wordsToRemove = new ArrayList<String>(); 
Set<String> seenWords = new HashSet<String>(); 

for (String word : userList) 
{ 
    if (!seenWords.add(word)) 
    { 
     wordsToRemove.add(word); 
    } 
} 

for (String word : wordsToRemove) 
{ 
    // Keep removing it until it doesn't exist any more 
    while (userList.remove(word)) {} 
} 

Bu ancak davayı görmezden gelmez. Bunu yapmak için, biraz daha akıllı olması gerekir:

Set<String> wordsToRemove = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); 
Set<String> seenWords = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); 

for (String word : userList) 
{ 
    if (!seenWords.add(word)) 
    { 
     wordsToRemove.add(word); 
    } 
} 

// Now we know the words we don't want, step through the list again and 
// remove them (case-insensitively, as wordsToRemove is case-insensitive) 
for (Iterator<String> iterator = userList.iterator(); it.hasNext() ;) 
{ 
    if (wordsToRemove.contains(word)) 
    { 
     iterator.remove(); 
    } 
} 
+1

Hiç uyumaz mısın? :( – musiKk

+4

@musiKk: Bkz. Http://meta.stackexchange.com/questions/555/ –

+1

@MusiKk ayrıca bkz. Http://meta.stackexchange.com/questions/9134/jon-skeet-facts –

1
ArrayList<String> copylist = userlist; 

Bu hat menu menu referans userlist atar ve yeni arraylist oluşturmaz. Aynı arraylist işaret eder. Yeni bir liste oluşturmak için, tamamen yeni bir liste oluşturmak ve öğenin yeni listede olup olmadığını kontrol ettikten sonra bu yeni listeye öğeler eklemeye devam etmektir.

ArrayList<String> newList = new ArrayList<String>(); 

foreach(String item in userList) { 
    if(newList.contains(item)==false) 
    { 
      newList.add(item); 
    } 
} 
+0

Bu, çoğaltılmamış bir liste ile sonuçlanacaktır - ancak yine de * bir "turuncu" örneğini içerecektir. –

+0

'foreach (userList içinde String öğesi)' bu Java değildir. Yani (String öğesi: userList) ' –

+0

@ S.P.Floyd için, üzgün foreach foreach demek. Java yıl önce ayrıldım .. şimdi C# 'da çalışıyorum, böylece foreach .. – Shekhar

1

Iyi sorunu bilinir - Eğer tekrarlanır konteyner değiştiremez. hüner çözmek için Yineleyiciyi yöntem kaldır kullanılmasıdır:

Iterator<String> tblIter = array.iterator(); 
    while (tblIter.hasNext()) { 
     String entry = tblIter.next(); 
     if(entry.equals(.....)) 
     { 
      ... 
      tblIter.remove(); 
     } 
    } 
+0

Ama her iki örneği de unutmamalısın. Bunun işe yarayacağından emin değilim. Cevabınız için teşekkürler, bir deneyin. –

2

toplanması yoluyla yineleme sırasında eleman Iterator ve Iterator.remove()

kullanmak zorunda Ama edilmesini istediğiniz kaldırmak istiyorsanız size daha kolay bir çözüm önermek için: listenizi hazırlayın. Otomatik olarak çiftleri kaldırır:

List<String> mylist = new ArrayList<String>(); 
// some initialization: there are duplicates 

Set<String> myset = new HashSet<String>(mylist); // no duplicates here. 

Bunu koleksiyon olduğu için set kullanmaya devam ederek bunun adımlayabilirsiniz.Sıralı erişimi gerekiyorsa Ama yine liste oluşturmak:

newlist = new ArrayList<String>(myset); 

elemanları karma bir sonucu olarak "rastgele" olacaktır sette sipariş. Orijinal siparişi korumak isterseniz HashSet yerine LinkedHashSet kullanın. nasıl/denetimi yoksa, diğer taraftan

add(element) 
{ 
    if arrayList.contains(element) 
     arrayList.remove(arrayList.indexOf(element)) 

    else 
     arrayList.add(element) 
} 

:

+0

Bu, her ikisini de kaldırmak yerine bir "turuncu" örneğiyle sonuçlanacaktır. Fikir, çoğaltılan herhangi bir değerin * tüm * kopyalarını kaldırmaktır. –

+0

Anladığım kadarıyla, o, her ikisinin de kaldırılacak bir yinelenen tekrarı olmasını istiyor. Ayrıca, siparişi korumak ve mevcut listeyi yeniden kullanmak için bir LinkedHashSet kullanabilirsiniz ('list.clear(); list.addAll (set);') – sfussenegger

0

veri eklendiğinde nasıl kontrol varsa, böyle bir şey kendi "add" yöntemini oluşturabilir veri eklenir, bir döngü yapabilir ve yukarıdaki gibi benzer bir mantığa sahip olabilirsiniz. Uygun yöntemler için here'a bakın.

+0

Teşekkürler! Aslında bunu denemeye başladım. Şu anki çözümüm çok benzer, ki bu çok garip geliyor ve programa daha fazla şey eklediğimde iyi çalışmayabilir. Bunu yapmanın en iyi yolunu bilmek istedim. –

4
import java.util.ArrayList; 
import java.util.HashSet; 
import java.util.List; 
import java.util.Set; 


public class Test { 
    public static void main(String[] args) { 
     List<String> a = new ArrayList<String>(); 
     a.add("apple"); 
     a.add("orange"); 
     a.add("banana"); 
     a.add("pear"); 
     a.add("peach"); 
     a.add("orange"); 
     System.out.println(a); 
     System.out.println(getSingleWordList(a)); 
    } 
    private static List<String> getSingleWordList(List<String> list) 
    { 
     Set<String> uniques = new HashSet<String>(); 
     Set<String> dups = new HashSet<String>(); 

     for (String a : list) 
      if (!uniques.add(a)) 
       dups.add(a); 


     uniques.removeAll(dups); 

     return new ArrayList<String>(uniques); 
    } 
} 

ÇIKIŞ objektif yinelenen elemanları olmadan bir koleksiyon ise

Input = [apple, orange, banana, pear, peach, orange]

Output = [pear, apple, banana, peach]

+3

Çok hoş - Bunu beğendim. Sipariş muhafazası gerekiyorsa 'LinkedHashSet 'kullanın. –

+0

anladığım kadarıyla, eski listenin değiştirilmesini istiyor, yeni bir tane değil. Böylece dönüş satırınızı 'list.clear(); list.addAll (uniques); ' – sfussenegger

0

, bir Set List daha uygun olacağını düşünün.

İlgili konular