我想搜索ArrayLst并删除任何相同的条目。
例如,如果我的列表是: 苹果,橙,香蕉,梨,桃,橙,
然后“橙色”将被删除(两次都出现)。
天真地,我试过了:
for(String word : userlist){
for(String otherword : userlist){
...
}
}
我写了如何.remove(lastIndexOf(userword))如果它等于单词和它们的索引是不同的。
这导致了异常后的异常,我很快意识到我在迭代它时正在操作列表,这使得一切都出错了。
所以决定制作一份清单
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));
}
}
}
所以我试过这个,它有类似的问题。特别是ConcurrentModificationException。在调整之后,我无法得到,在我脑海中应该是一个相当简单的过程,在Java中工作。请帮忙。
答案 0 :(得分:10)
您目前根本没有制作该列表的副本。您正在声明一个新变量,该变量具有对同一列表的引用。要制作列表的副本,请使用:
ArrayList<String> copyList = new ArrayList<String>(userList);
但是,我建议采用不同的方法:
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)) {}
}
然而, 不会忽略大小写。要做到这一点,你需要更聪明一点:
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 :(得分: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);
}
}
<强>输出强>
Input = [apple, orange, banana, pear, peach, orange]
Output = [pear, apple, banana, peach]
答案 2 :(得分:2)
如果您希望在迭代过程中删除元素,则必须使用Iterator和Iterator.remove()
但我想建议您更简单的解决方案:将您的列表放入设置中。它会自动删除重复项:
List<String> mylist = new ArrayList<String>();
// some initialization: there are duplicates
Set<String> myset = new HashSet<String>(mylist); // no duplicates here.
您可以继续使用set,因为它是集合,您可以迭代它。但如果您需要随机访问再次创建列表:
newlist = new ArrayList<String>(myset);
由于散列,set中的元素顺序将是“随机的”。如果您希望保留原始订单,请使用LinkedHashSet而不是HashSet。
答案 3 :(得分:1)
ArrayList<String> copylist = userlist;
此行将引用用户列表分配给copylist,但不会创建新的arraylist。它指向相同的arraylist。 要创建一个新列表,简单的方法是创建新的列表并在检查项目是否已经存在于新列表中之后继续在此新列表中添加项目。
ArrayList<String> newList = new ArrayList<String> ();
foreach(String item in userList) {
if(newList.contains(item)==false)
{
newList.add(item);
}
}
答案 4 :(得分:1)
众所周知的问题 - 您无法修改迭代的容器。 要解决的诀窍是使用方法删除Iterator:
Iterator<String> tblIter = array.iterator();
while (tblIter.hasNext()) {
String entry = tblIter.next();
if( entry.equals(.....) )
{
...
tblIter.remove();
}
}
答案 5 :(得分:0)
如果您可以控制数据的添加方式,您可以创建自己的“添加”方法,如下所示:
add(element)
{
if arrayList.contains(element)
arrayList.remove(arrayList.indexOf(element))
else
arrayList.add(element)
}
另一方面,如果您无法控制添加数据的方式/时间,则可以进行循环,其中的逻辑与上述类似。看看here的相应方法。
答案 6 :(得分:0)
如果目标是没有重复元素的集合,请考虑Set是否比List更合适。