从ArrayList中删除重复项

时间:2011-04-21 07:41:11

标签: java

我有一个自定义对象的ArrayList。我想删除重复的条目。

对象有三个字段:title, subtitleid。如果一个字幕出现多次,我只需要带有那个副标题的第一个项目(忽略带有该副标题的剩余对象)。

14 个答案:

答案 0 :(得分:50)

您可以使用自定义Comparator将ArrayList的内容放在TreeSet中,如果两个字幕相同,则应返回0。 之后,您可以转换列表中的Set并使列表没有“重复”。 这是Object的一个例子,当然你应该使用正确的类和逻辑。

public void removeDuplicates(List<Object> l) {
    // ... the list is already populated
    Set<Object> s = new TreeSet<Object>(new Comparator<Object>() {

        @Override
        public int compare(Object o1, Object o2) {
            // ... compare the two object according to your requirements
            return 0;
        }
    });
            s.addAll(l);
    List<Object> res = Arrays.asList(s.toArray());
}

答案 1 :(得分:46)

List list = (...);

//list may contain duplicates.

//remove duplicates if any
Set setItems = new LinkedHashSet(list);
list.clear();
list.addAll(setItems);

你可能需要覆盖“equals()”,这样如果2个元素具有相同的字幕(或者可能是字号和副标题,那么它们被视为等号)。

答案 2 :(得分:11)

我建议使用Set

http://download.oracle.com/javase/6/docs/api/java/util/Set.html

其性质不能包含重复的项目。您可以使用

从原始ArrayList创建新集
Set myset = new HashSet(myArrayList);

或者,只需从头开始使用Set,不要使用ArrayList,因为它没有执行您需要的功能。

答案 3 :(得分:10)

List<Item> result = new ArrayList<Item>();
Set<String> titles = new HashSet<String>();

for(Item item : originalList) {
    if(titles.add(item.getTitle()) {
        result.add(item);
    }
}
如果元素已存在,则add()的{​​p} Set会返回false

答案 4 :(得分:7)

您可以使用O(n ^ 2)解决方案:使用list.iterator()迭代列表一次,并在每次迭代时再次迭代以检查是否存在重复。如果有 - 请致电iterator.remove()。其中一个变体是使用guava的Iterables.filter(list, predicate),其中过滤逻辑位于谓词中。

另一种方式(可能更好)是定义equals(..)hashCode(..)方法来处理自定义相等逻辑,然后简单地构造一个new HashSet(list)。这将清除重复。

答案 5 :(得分:6)

如果我理解正确你有ArrayList<Custom>,我们称之为list。您的Custom班级有一个字幕字段,假设使用getSubtitle()方法返回String。您只想保留第一个唯一的字幕并删除任何剩余的副本。以下是您可以这样做的方法:

Set<String> subtitles = new HashSet<String>();
for (Iterator<Custom> it = list.iterator(); it.hasNext(); ) {
    if (!subtitles.add(it.next().getSubtitle())) {
        it.remove();
    }
}

答案 6 :(得分:4)

删除集合中的所有重复项,同时保留订单(如果它是有序集合)。对大多数情况来说足够有效。

public static <I, T extends Collection<I>> T removeDuplicates(T collection)
{
    Set<I> setItems = new LinkedHashSet<I>(collection);
    collection.clear();
    collection.addAll(setItems);

    return collection;
}

答案 7 :(得分:2)

使用Collections.sort()对一个简单的循环进行排序和使用以捕获双精度数,例如:

docker run --volumes-from my_datastore ...

这假设您将在A类中实现Comparable。

答案 8 :(得分:2)

Java8更新:

使用Java8流你也可以非常简单。

ArrayList<String> deduped;
deduped = yourArrayList.stream()
             .distinct()
             .collect(Collectors.toCollection(ArrayList::new));

这比保持排序的 ArrayList Set ArrayList 更具优势。

答案 9 :(得分:1)

private static List<Integer> removeDuplicates(List<Integer> list) {
    ArrayList<Integer> uniqueList = new ArrayList<Integer>();
    for (Integer i : list) {
        if (!inArray(i, uniqueList)) {
            uniqueList.add(i);
        }
    }

    return uniqueList;
}

private static boolean inArray(Integer i, List<Integer> list) {
    for (Integer integer : list) {
        if (integer == i) {
            return true;
        }
    }

    return false;
}

答案 10 :(得分:0)

List<YourObject> all = ******** // this is the object that you have already  and filled it.
List<YourObject> noRepeat= new ArrayList<YourObject>();

for (YourObject al: all) {
    boolean isPresent = false;
    // check if the current objects subtitle already exists in noRepeat
    for (YourObject nr : noRepeat) {
        if (nr.getName().equals(al.getName()) {
            isFound = true;//yes we have already
            break;
        }
    }

    if (!isPresent)
        noRepeat.add(al); // we are adding if we don't have already
}
  

获取一个相同类型的新ArrayList对象
  逐个将所有旧的arraylists元素添加到这个新的arraylist对象中   但在添加每个对象之前,请检查新的arraylist,如果有任何对象具有相同的副标题。如果新的arraylist包含这样的副标题,请不要添加它。否则加上

答案 11 :(得分:0)

解决方案取决于具体情况。

如果您没有太多数据,请使用Set Set<T> unique = new HashSet<>(yourList);(如果您关心订单,请使用LinkedHashSet。它会创建一个新集合,但通常不会有问题。

如果要修改现有列表并且不想/不能创建新集合,可以删除重复项,如下所示:

List<Integer> numbers =
    new ArrayList<>(asList(1, 1, 2, 1, 2, 3, 5));

System.out.println("Numbers: " + numbers);
ListIterator<Integer> it = numbers.listIterator();
while (it.hasNext()) {
    int i = it.nextIndex();
    Integer current = it.next();
    for (int j = 0; j < i; ++j) {
        if (current.equals(numbers.get(j))) {
            it.remove();
            break;
        }
    }
}
System.out.println("Unique: " + numbers);

它适用于O(n ^ 2),但它有效。类似的实现,但更简单,是在列表排序时 - 在O(n)时间内工作。这两种实现都在Farenda中解释:remove duplicates from list - various implementations

答案 12 :(得分:0)

使用Java 8流的另一种方法也可以做得很酷:

List<Customer> CustomerLists;
List<Customer> unique = CustomerLists.stream().collect(collectingAndThen(
        toCollection(() -> new TreeSet<>(comparingLong(Customer::getId))),
        ArrayList::new));

答案 13 :(得分:0)

在Java 8中,您还可以执行以下操作:

"name"

诀窍是收集要映射的流,并提供始终返回其第一个参数的关键冲突解析器lambda(yourList.stream().collect( Collectors.toMap( obj -> obj.getSubtitle(), Function.identity(), (o1,o2) -> o1)) .values(); )。 结果是一个Collection,而不是一个List,但是您可以轻松地将其转换为List:

(o1,o2) -> o1