546

我有一个ArrayList<String>,我想从中删除重复的字符串。我怎样才能做到这一点?

4

39 回答 39

1062

如果您不想在 a 中重复Collection,您应该考虑为什么要使用Collection允许重复的 a。删除重复元素的最简单方法是将内容添加到 a Set(不允许重复),然后将Set后面添加到ArrayList

Set<String> set = new HashSet<>(yourList);
yourList.clear();
yourList.addAll(set);

当然,这会破坏ArrayList.

于 2008-10-15T08:11:27.693 回答
307

尽管将 转换ArrayList为 a 可以HashSet有效地删除重复项,但如果您需要保留插入顺序,我宁愿建议您使用此变体

// list is some List of Strings
Set<String> s = new LinkedHashSet<>(list);

然后,如果需要取回List引用,可以再次使用转换构造函数。

于 2008-10-15T08:18:19.550 回答
153

在 Java 8 中:

List<String> deduped = list.stream().distinct().collect(Collectors.toList());

请注意,应遵守列表成员的hashCode-equals合同,以使过滤正常工作。

于 2014-04-20T01:23:18.067 回答
66

假设我们有一个String类似的列表:

List<String> strList = new ArrayList<>(5);
// insert up to five items to list.        

然后我们可以通过多种方式删除重复元素。

在 Java 8 之前

List<String> deDupStringList = new ArrayList<>(new HashSet<>(strList));

注意:如果我们想保持插入顺序,那么我们需要使用LinkedHashSet代替HashSet

使用番石榴

List<String> deDupStringList2 = Lists.newArrayList(Sets.newHashSet(strList));

使用 Java 8

List<String> deDupStringList3 = strList.stream().distinct().collect(Collectors.toList());

注意: 如果我们想在特定的列表实现中收集结果,例如LinkedList,我们可以将上面的示例修改为:

List<String> deDupStringList3 = strList.stream().distinct()
                 .collect(Collectors.toCollection(LinkedList::new));

我们也可以parallelStream在上面的代码中使用,但它可能不会带来预期的性能优势。检查此问题以获取更多信息。

于 2016-05-24T06:17:57.090 回答
53

如果您不想重复,请使用Set而不是List. 要将 a 转换List为 a,Set您可以使用以下代码:

// list is some List of Strings
Set<String> s = new HashSet<String>(list);

如果确实有必要,您可以使用相同的结构将 a 转换SetList.

于 2008-10-15T08:13:48.343 回答
30

您也可以这样做,并保持顺序:

// delete duplicates (if any) from 'myArrayList'
myArrayList = new ArrayList<String>(new LinkedHashSet<String>(myArrayList));
于 2016-11-04T09:47:10.770 回答
28

这是一种不会影响您的列表排序的方法:

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 是原始列表,l2 是没有重复项的列表(确保 YourClass 根据您要代表相等的内容具有 equals 方法)

于 2010-12-28T16:07:10.687 回答
27

Java 8 流提供了一种非常简单的方法来从列表中删除重复元素。使用不同的方法。如果我们有一个城市列表,并且我们想从该列表中删除重复项,则可以在一行中完成 -

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

如何从数组列表中删除重复元素

于 2015-08-12T17:30:38.417 回答
22

这可以解决问题:

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;
}
于 2013-10-10T20:24:46.860 回答
21

也有ImmutableSet来自Guava的选项(这里是文档):

ImmutableSet.copyOf(list);
于 2011-12-09T22:55:49.180 回答
21

可以在不使用HashSet另一个arraylist 的情况下从 arraylist 中删除重复项。

试试这个代码..

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

输出是

Duplicates List [ABC, ABC, ABCD, ABCD, ABCE]
Distinct List [ABC, ABCD, ABCE]
于 2013-10-17T18:38:14.440 回答
12

可能有点矫枉过正,但我​​喜欢这种孤立的问题。:)

此代码使用临时 Set(用于唯一性检查),但直接删除原始列表中的元素。由于 ArrayList 中的元素删除会导致大量的数组复制,因此避免了 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);
    }
}

当我们这样做的时候,这里有一个 LinkedList 的版本(好多了!):

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

使用marker界面呈现List的统一解决方案:

public static <T> void removeDuplicates(List<T> list) {
    if (list instanceof RandomAccess) {
        // use first version here
    } else {
        // use other version here
    }
}

编辑:我猜泛型的东西在这里并没有真正增加任何价值。哦,好吧。:)

于 2008-10-18T16:11:35.457 回答
12
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);
}
于 2015-09-20T14:41:56.813 回答
5

如果您愿意使用第三方库,可以使用Eclipse Collections(以前称为 GS Collections)distinct()中的方法。

ListIterable<Integer> integers = FastList.newListWith(1, 3, 1, 2, 2, 1);
Assert.assertEquals(
    FastList.newListWith(1, 3, 2),
    integers.distinct());

使用distinct()而不是转换为 Set 然后返回到 List的优点是distinct()保留了原始 List 的顺序,保留了每个元素的第一次出现。它是通过使用 Set 和 List 来实现的。

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;

如果您无法将原始 List 转换为 Eclipse Collections 类型,则可以使用 ListAdapter 获取相同的 API。

MutableList<Integer> distinct = ListAdapter.adapt(integers).distinct();

注意:我是 Eclipse Collections 的提交者。

于 2015-12-10T14:46:58.367 回答
4

如果您使用模型类型 List< T>/ArrayList< T> 。希望,对你有帮助。

这是我的代码,没有使用任何其他数据结构,如 set 或 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--;
  }
 }
}
于 2018-05-09T12:54:46.867 回答
3

如果您想保留您的订单,那么最好使用LinkedHashSet。因为如果您想通过迭代将此列表传递给插入查询,则将保留顺序。

试试这个

LinkedHashSet link=new LinkedHashSet();
List listOfValues=new ArrayList();
listOfValues.add(link);

当您想要返回 List 而不是 Set 时,这种转换将非常有用。

于 2013-10-12T12:51:01.780 回答
3

这三行代码可以从 ArrayList 或任何集合中删除重复的元素。

List<Entity> entities = repository.findByUserId(userId);

Set<Entity> s = new LinkedHashSet<Entity>(entities);
entities.clear();
entities.addAll(s);
于 2014-12-08T10:57:39.617 回答
2

填充 ArrayList 时,为每个元素使用一个条件。例如:

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

我们将得到一个数组 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

于 2011-04-11T08:17:38.553 回答
2

代码:

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

注意:肯定会有内存开销。

于 2015-03-11T12:47:31.060 回答
2
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();
于 2016-03-26T10:13:30.243 回答
2

您可以在下面使用嵌套循环:

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);
        }
于 2017-11-30T18:40:58.163 回答
1

如前所述,您应该使用实现 Set 接口的类而不是 List 来确保元素的唯一性。如果必须保持元素的顺序,则可以使用 SortedSet 接口;TreeSet 类实现了该接口。

于 2008-10-15T13:48:30.757 回答
1
for(int a=0;a<myArray.size();a++){
        for(int b=a+1;b<myArray.size();b++){
            if(myArray.get(a).equalsIgnoreCase(myArray.get(b))){
                myArray.remove(b); 
                dups++;
                b--;
            }
        }
}
于 2012-01-22T15:23:18.183 回答
1

LinkedHashSet 可以解决问题。

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

//输出:5,1,2,3,4

于 2013-01-02T17:06:41.123 回答
1
        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]
于 2015-08-02T09:54:03.153 回答
1

这用于您的自定义对象列表

   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;
}
于 2017-03-26T06:19:13.793 回答
0
import java.util.*;
class RemoveDupFrmString
{
    public static void main(String[] args)
    {

        String s="appsc";

        Set<Character> unique = new LinkedHashSet<Character> ();

        for(char c : s.toCharArray()) {

            System.out.println(unique.add(c));
        }
        for(char dis:unique){
            System.out.println(dis);
        }


    }
}
于 2012-09-30T21:45:41.383 回答
0
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;
        }
于 2013-08-29T07:21:09.310 回答
0
    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);
于 2014-06-13T12:51:39.000 回答
0

如果要从 ArrayList 中删除重复项,则意味着找到以下逻辑,

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;
}
于 2014-09-11T06:52:56.530 回答
0

@jonathan-stafford 解决方案是可以的。但这不会保留列表顺序。

如果要保留列表顺序,则必须使用:

public static <T> void removeDuplicate(List <T> list) {
Set <T> set = new HashSet <T>();
List <T> newList = new ArrayList <T>();
for (Iterator <T>iter = list.iterator();    iter.hasNext(); ) {
   Object element = iter.next();
   if (set.add((T) element))
      newList.add((T) element);
   }
   list.clear();
   list.addAll(newList);
}

这只是为了完成答案。很好!

于 2015-07-01T11:54:45.330 回答
0

这是我的答案,没有使用任何其他数据结构,如 set 或 hashmap 等。

public static <T> ArrayList<T> uniquefy(ArrayList<T> myList) {

    ArrayList <T> uniqueArrayList = new ArrayList<T>();
    for (int i = 0; i < myList.size(); i++){
        if (!uniqueArrayList.contains(myList.get(i))){
            uniqueArrayList.add(myList.get(i));
        }
    }

    return uniqueArrayList;
}
于 2015-09-23T09:36:02.547 回答
0

像这样的东西会更好吗?

public static void removeDuplicates(ArrayList<String> list) {
    Arraylist<Object> ar     = new Arraylist<Object>();
    Arraylist<Object> tempAR = new Arraylist<Object>();
    while (list.size()>0){
        ar.add(list(0));
        list.removeall(Collections.singleton(list(0)));
    }
    list.addAll(ar);
}

那应该保持顺序,并且在运行时也不是二次的。

于 2015-12-02T02:23:21.667 回答
0

时间复杂度:O(n):没有设置

private static void removeDup(ArrayList<String> listWithDuplicateElements) {
    System.out.println(" Original Duplicate List :" + listWithDuplicateElements);
    List<String> listWithoutDuplicateElements = new ArrayList<>(listWithDuplicateElements.size());

    listWithDuplicateElements.stream().forEach(str -> {
        if (listWithoutDuplicateElements.indexOf(str) == -1) {
            listWithoutDuplicateElements.add(str);
        }
    });     

    System.out.println(" Without Duplicate List :" + listWithoutDuplicateElements);
}
于 2018-05-17T02:53:05.023 回答
0

这是正确的(如果您担心 HashSet 的开销。

 public static ArrayList<String> removeDuplicates (ArrayList<String> arrayList){
    if (arrayList.isEmpty()) return null;  //return what makes sense for your app
    Collections.sort(arrayList, String.CASE_INSENSITIVE_ORDER);
    //remove duplicates
    ArrayList <String> arrayList_mod = new ArrayList<>();
    arrayList_mod.add(arrayList.get(0));
    for (int i=1; i<arrayList.size(); i++){
        if (!arrayList.get(i).equals(arrayList.get(i-1))) arrayList_mod.add(arrayList.get(i));
    }
    return arrayList_mod;
}
于 2018-07-05T00:14:17.103 回答
0
Set<String> strSet = strList.stream().collect(Collectors.toSet());

是删除重复项的最简单方法。

于 2019-02-08T15:20:31.850 回答
0

如果您希望您的列表自动忽略重复项并保留其顺序,您可以创建一个HashList(一个 HashMap 嵌入式列表)。

public static class HashList<T> extends ArrayList<T>{
        private HashMap <T,T> hashMap;
        public HashList(){
            hashMap=new HashMap<>();
        }

        @Override
        public boolean add(T t){
            if(hashMap.get(t)==null){
                hashMap.put(t,t);
                return super.add(t);
            }else return false;
        }

        @Override
        public boolean addAll(Collection<? extends T> c){
            HashList<T> addup=(HashList<T>)c;
            for(int i=0;i<addup.size();i++){
                add(addup.get(i));
            }return true;
        }

    }

Usage Example:

HashList<String> hashlist=new HashList<>();
hashList.add("hello");
hashList.add("hello");
System.out.println(" HashList: "+hashlist);
于 2019-03-09T01:44:37.810 回答
0

这是一个适用于任何对象的解决方案:

public static <T> List<T> clearDuplicates(List<T> messages,Comparator<T> comparator) {
    List<T> results = new ArrayList<T>();
    for (T m1 : messages) {
        boolean found = false;
        for (T m2 : results) {
            if (comparator.compare(m1,m2)==0) {
                found=true;
                break;
            }
        }
        if (!found) {
            results.add(m1);
        }
    }
    return results;
}
于 2021-10-08T17:59:20.797 回答
-2

在 Java 中,List 允许对其元素进行有序访问。它们可以有重复项,因为它们的查找键是位置而不是某个哈希码,每个元素都可以在它们保留在列表中时进行修改,其中 Set 表示唯一元素的集合,并且当元素在集合中时,它们不能被修改。虽然没有限制阻止您修改集合中的元素,如果元素被修改,那么它可能会永远丢失在集合中。

public static void main(String[] args) {
       List<String> l = new ArrayList<String>();
       l.add("A");
       l.add("B");
       l.add("C");
       l.add("A");
       System.out.println("Before removing duplicates: ");
       for (String s : l) {
            System.out.println(s);
       }
       Set<String> set = new HashSet<String>(l);
       List<String> newlist = new ArrayList<String>(set);
       System.out.println("after removing duplicates: ");
       for (String s : newlist) {
            System.out.println(s);
       }
  }

作为参考,请参阅此链接如何从 ArrayList 中删除重复项

于 2015-11-17T07:26:39.697 回答