0

EDITED/SOLVED still looking for better answer I do have a answer here How do I remove repeated elements from ArrayList? and it is working my question is relation to ONLY list and not Set. Since through out application flow list has been implemented and it is difficult for me to change all List references to Set reference as https://docs.oracle.com/javase/7/docs/api/java/util/List.html has get(..) Set doesn't have get(..).

Each object getting added is a new Instance. hi i Have a model class

public final class MyClass implements Comparable<MyClass> {

    public static final int APP = 0;
    public static final int FILE = 1;
    public static final int FOLDER = 2;

    private String name;
    private String path;
    private String pkg;
    private Long size;
    private boolean selected;
    private Integer type;


    public MyClass(String name, String path, String pkg, Long size, boolean selected, int type) {
        this.name = name;
        this.path = path;
        this.pkg = pkg;
        this.size = size;
        this.selected = selected;
        this.type = type;


        if (!TextUtils.isEmpty(path)) {
            File file = new File(path);
            if (file.exists()) {
                this.size = file.length();
            }
        }
    }

    public String getName() {
        return name;
    }

    public String getPath() {
        return path;
    }

    public String getSize() {
        return FileUtils.getReadableFileSize(size);
    }

    public boolean isSelected() {
        return selected;
    }

    public void setSelected(boolean selected) {
        this.selected = selected;
    }


    public Integer getType() {
        return type;
    }

    public String getPkg() {
        return pkg;
    }

    @Override
    public String toString() {
        return "{Pkg=" + pkg + ", Path=" + path + ", size=" + size + ", hashcode: " + hashCode() +"}";
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;

        if (o == null || getClass() != o.getClass())
            return false;

        MyClass myclass = (MyClass) o;

        if (path != null ? !path.equals(myclass.path) : myclass.path != null)
            return false;

        if (pkg != null ? !pkg.equals(myclass.pkg) : myclass.pkg != null)
            return false;

        return size != null ? size.equals(myclass.size) : myclass.size == null;

    }

    @Override
    public int hashCode() {
        int result = path != null ? path.hashCode() : 0;
        result = 31 * result + (pkg != null ? pkg.hashCode() : 0);
        result = 31 * result + (size != null ? size.hashCode() : 0);
        return result;
    }

    @Override
    public int compareTo(MyClass myclass) {
        return myclass.getType().compareTo(this.type);
    }
}

But when i create common object, these object are getting added to list, even though their hashcode is same it is duplicate in list. Anything i may be doing wrong here.

Output of toString of List is as follows:

[{
    Pkg = com.a.bc,
    Path = /data/app / com.a.bc - 1 / base.apk,
    size = 1800820,
    hashcode: -908060882
}, {
    Pkg = com.a.b.c,
    Path = /data/app / com.a.b.c - 1 / base.apk,
    size = 21279534,
    hashcode: 1116685502
}, {
    Pkg = com.a.b.c,
    Path = /data/app / com.a.b.c - 1 / base.apk,
    size = 21279534,
    hashcode: 1116685502
}]

Here is some dirty implementation but this is not what i was looking for...

private final class DuplicateFilterArrayList<E> extends ArrayList<E> {

        private DuplicateFilterArrayList() {

        }

        @Override
        public boolean add(E object) {
            if (object instanceof MyClass) {
                if (!contains(object)) {
                    return super.add(object);
                } else {
                    Logger.error(TAG, "Object already exists go home");
                    return false;
                }
            } else {
                throw new IllegalArgumentException("Unsupported Object type " + object.getClass().getSimpleName());
            }
        }

        @Override
        public boolean contains(Object object) {
            if (object instanceof MyClass) {
                MyClass otherMyClassObjec = (MyClass) object;
                for (E myClassItem : this) {
                    MyClass newMyClass = (MyClass) myClassItem;
                    if (newMyClass.equals(otherMyClassObjec) && newMyClass.hashCode() == otherMyClassObjec.hashCode()) {
                        return true;
                    }
                }
            }

            return false;
        }

    }
Community
  • 1
  • 1
silentsudo
  • 6,730
  • 6
  • 39
  • 81
  • 2
    Why would you expect that a `List` would not contain duplicates? A `List` does not check for duplicates, only a `Set` would do that. You have not shown the code that creates and adds entries to the `List`. – Jim Garrison Dec 02 '16 at 06:26
  • @CoffeeMonkey its completely new instance each time but its properites are more or similar. – silentsudo Dec 02 '16 at 06:36
  • Sorry, that makes no sense. A `List` will not prevent duplicates. You must use a `Set` if you want to prevent duplicates from being stored. – Jim Garrison Dec 02 '16 at 06:38
  • @JimGarrison Yes correct no doubt but changing whole implementation also doesn't make sense. – silentsudo Dec 02 '16 at 06:43
  • `List` is the wrong data type for this. The implementation is WRONG and must be changed. You're saying "I designed this car with square wheels and it's too late to change the implementation". – Jim Garrison Dec 02 '16 at 06:45
  • everytime we are not the same people who design them ;) – silentsudo Dec 02 '16 at 06:51

2 Answers2

1

Before adding to the list, check if the instance is already in the Collection by using the contains method on the Collection (List in this case). Then you can choose to not add again if it's already contained. It should work if you've correctly implemented the equals and hashCode methods.

Coffee Monkey
  • 481
  • 2
  • 7
0

Create your own class(MYArrayList) which extend ArrayList. Make return type as list itself. Rest all will be same.

List list = new MyArrayList

MyArrayList extends ArrayList<>

override add method of MyArrayList such that before adding MYClass in List its Check if this List contains it already or not.

But remember this will degrade the performance since it will iterate over all elements in list just to check duplicacy in insertion.

Roshan
  • 2,144
  • 2
  • 16
  • 28
  • Yes this is one of possibility and it works fine but many changes to list object instatiation. List myList = new MyCustomList(); – silentsudo Dec 02 '16 at 06:53
  • Yes, that will be required to do. In how many place you have such initialization. Better to give an API and have it at only one place ,which will help you in future also – Roshan Dec 02 '16 at 06:56
  • you answer is what i implemented as partial solution but not the final one. – silentsudo Dec 02 '16 at 07:33