Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
343 views
in Technique[技术] by (71.8m points)

java - How to use Collections methods(removeAll() and retainAll()) for two objects. (objects are parent-child relation)

I expected to result below but actually not. I would like to know how to show the differences between two Collections. (objects are parent and child relationship) In this case, can I use standard method like removeAll() or can you recommend another approach like using apache-commons. Thanks.

CONSTRAINT
------------------------------
1.Item.class is unmodifiable(eg. I can not add equals method)
2.If id is same between two objects, they are assumed as same things.
------------------------------

EXPECTED
------------------------------
removed object are:
2
same object are:
1
3
add object are:
4
------------------------------

ACTUAL
------------------------------
removed object are:
1
2
3
same object are:
add object are:
1
3
4
------------------------------

package com.javastudy;

import java.util.ArrayList;
import java.util.List;

public class CollectionCompareToObjects {

    public static void main(String[] args) {

        List<Item> before = new ArrayList<Item>();
        List<ItemEx> after = new ArrayList<ItemEx>();

        before.add(new Item(1L));
        before.add(new Item(2L)); // delete
        before.add(new Item(3L));

        after.add(new ItemEx(1L));
        after.add(new ItemEx(3L));
        after.add(new ItemEx(4L)); // added

        List<Item> removed = new ArrayList<Item>(before);
        removed.removeAll(after);

        System.out.println("removed objects are:");
        for(Item item : removed){
            System.out.println(item.getId());
        }

        List<Item> same = new ArrayList<Item>(before);
        same.retainAll(after);

        System.out.println("same objects are:");
        for(Item item : same){
            System.out.println(item.getId());
        }

        List<Item> added = new ArrayList<Item>(after);
        added.removeAll(before);

        System.out.println("add objects are:");
        for(Item item : added){
            System.out.println(item.getId());
        }

    }

}


package com.javastudy;

public class Item {

    private Long id;

    public Item(Long id) {
        this.id = id;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

}

package com.javastudy;

public class ItemEx extends Item {

    private String name;

    public ItemEx(Long id) {
        super(id);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Java collections rely on the equals and hashCode methods (the latter is used by HashMaps, HashSets and others).

If you want to be able to use the data structure capabilities of Java collections (such as removeAll, retainAll etc.), you need to supply objects with proper implementations of equals and hashCode.

If you can't modify the Item class, you can write a wrapper class with your own implementation of equals:

public class ItemWrapper {
    private final Item item;
    public ItemWrapper(Item item) {
        this.item = item;
    }

    public Item getItem() {
        return item;
    }

    @Override
    public boolean equals(Object obj) {
        return obj instanceof ItemWrapper && item.getId().equals(((ItemWrapper) obj).item.getId());
    }

    @Override
    public int hashCode() {
        return item.getId().hashCode();
    }
}

Create a new ItemWrapper for each original Item, store the ItemWrappers in Java collections, and use the required methods (removeAll/retainAll). Then iterate over the resulting collection and retrieve the Items by calling each ItemWrapper's getItem() method.

Your other option is to subclass ArrayList, but it seems like a more convoluted solution.

Yet another option is not to use Java collections for the remove/retain logic, implementing them yourself instead.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...