简体   繁体   English

从两个自定义对象列表中删除通用元素

[英]Removing common elements from two lists of custom objects

In the below code I have two Lists of image objects (fromTagList and fromImageList). 在下面的代码中,我有两个图像对象列表(fromTagList和fromImageList)。 The image class has an attribute image URL. 图像类具有属性图像URL。 There are common objects in the both lists. 这两个列表中都有共同的对象。

My goal is to detect these common elements according to their URL property and remove them from both lists, so that both lists will contain distinct elements together and then I will merge the two lists with one list so that this merged list will contain distinct objects. 我的目标是根据URL属性来检测这些公共元素,并将其从两个列表中删除,以便两个列表将包含不同的元素,然后将两个列表与一个列表合并,以便此合并的列表将包含不同的对象。 The problem is that the below method I used did not remove all common elements because I think like this it will skip some indexes. 问题是我使用的以下方法并未删除所有常见元素,因为我认为这样会跳过一些索引。

for (int i = 0; i < fromTagList.size(); i++) {
    for (int k = 0; k < fromImageList.size(); k++) {
        if (fromTagList.get(i).getImageURL().equals(fromImageList.get(k).getImageURL())) {
            fromTagList.remove(i);
            fromImageList.remove(k);
        }
    }
}

.remove(index) takes away the element, which makes the list shorter, but your index doesn't consider that, and keeps adding 1 but that actually steps over 2 elements (the +1 and the removed one). .remove(index)删除了元素,这使列表更短,但是您的索引没有考虑该元素,并继续添加1,但是实际上跳过了2个元素(+1和删除的元素)。

This works for inline removing of the repeated elements, but it fails when one list contains repeated elements. 这适用于内联删除重复的元素,但是当一个列表包含重复的元素时失败。 It works for the case where there are no repeated elements inside a list, because I go through the elements backwards. 它适用于列表中没有重复元素的情况,因为我向后浏览这些元素。 Do note the labelled continue. 请注意标记为继续。

//the new ArrayList is needed so remove is supported
    List<String> fromTagList = new ArrayList(Arrays.asList(new String[] {"a", "b", "c", "1", "2", "3"}));
    List<String> fromImageList = new ArrayList(Arrays.asList(new String[] {"b", "b", "c", "d", "2", "3", "4"}));

    outer: for (int i = fromTagList.size()- 1; i >= 0; i--) {
        for (int k = fromImageList.size() - 1; k >= 0; k--) {
        System.out.println("i: " + i + " k: " + k);
        if (fromTagList.get(i).equals(fromImageList.get(k))) {
            fromTagList.remove(i);
            fromImageList.remove(k);
            continue outer;
        }
        }
    }

    System.out.println("fromTag  : " + fromTagList);
    System.out.println("fromImage: " + fromImageList);

I don't think you can remove as you go if you want to support lists with repeated elements. 如果您想支持包含重复元素的列表,我认为您不能随便删除。 I suggest adding to a new list of elements to remove. 我建议添加到要删除的新元素列表中。

I would create a dictionary. 我会创建一个字典。 Iterate through each list (separately). 遍历每个列表(单独)。 For each object, push it onto the dictionary with the key being its URL. 对于每个对象,将其作为URL推入字典。 This way, any object with the same URL will appear as one key-value pair in the dictionary. 这样,任何具有相同URL的对象都将在字典中显示为一对键值对。 After adding everything to the dictionary, convert the dictionary to a list. 将所有内容添加到字典后,将字典转换为列表。

Yeah, You do have a problem of Index, the issue is when you delete something from the list, say at position i=10, the element of position 11 will be in the 10th and i will be in 11 so you will miss this element, the second issue is when you remove from the second list of k indexer, you should break, to not process all the rest elements (unless the element found is not duplicated), so here is my answer that work for me after trying your code: 是的,您确实有一个索引问题,问题是当您从列表中删除某项内容时,例如在位置i = 10处,位置11的元素将排在第10位,而我将在11位,因此您将错过此元素,第二个问题是,当您从第二个k索引器列表中删除时,应该中断操作,以不处理所有其余元素(除非找到的元素不重复),因此这是在尝试您的代码后对我有用的答案:

for (int i = 0; i < fromTagList.size(); i++) {
            for (int k = 0; k < fromImageList.size(); k++) {
                if (fromTagList.get(i).getImageURL().equals(fromImageList.get(k).getImageURL())) {
                    fromTagList.remove(i);
                    fromImageList.remove(k);
                    i--;
                    //break; this is optional
                }
            }
        }

Whenever you need to maintain uniq elements consider using Set<>. 每当需要维护uniq元素时,请考虑使用Set <>。 The set interface in java is specifically meant to handle uniq elements.You can follow the below approach to convert the lists to a set: java中的set接口专门用于处理uniq元素。您可以按照以下方法将列表转换为set:

Override the equals and hashcode method for the image object(use only the url attribute as a condition for equality and hascode). 覆盖图像对象的equals和hashcode方法(仅将url属性用作相等性和hascode的条件)。 Now add both the lists to a set. 现在将两个列表都添加到集合中。 Convert the set back to a list and voila!! 将设置转换回列表,瞧! Example: 例:

 class ImageObj {

    String url;
    //rest of the stuff

    @Override
    public boolean equals(Object o){
    ImageObj that = (ImageObj)o;
    return that.url.equals(this.url);
    }
    @Override
    public int hascode(){
    return Objects.hascode(this.url);
    }
    }
    }

Then-- 然后 -

Set<ImageObj> set= new HashSet<ImageObj>(fromTagList);
set.addAll(fromImageList);

List<ImageObj> list = new ArrayList<ImageObj>(set);

This is you final list which contains all unique objects. 这是您包含所有唯一对象的最终列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM