Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove an object from an ArrayList given only one attribute

I have an ArrayList of Items and I want to be able remove one Item from the list by entering only one Item attribute, for example its number (int ItemNumber). I also wanna do the same when I check Item quantities.

These are my equals() & contains() methods, do I need to make any changes here?

public boolean contains(T anEntry) {
    boolean found = false;
    for (int index = 0; !found && (index < numberOfEntries); index++) {
    if (anEntry.equals(list[index])) 
        found = true;
    }//end for
    return found;
} // end contains

public boolean equals(Object object){
    Item item = (Item) object;
    if (itemNo == item.itemNo)
        return true;
    return false;
}
like image 996
helloworld Avatar asked Mar 19 '15 19:03

helloworld


2 Answers

If you change the class Item equals() and compareTo() methods, so that they check only one object field, such as a quantity, it could result in strange behavior in other parts of your application. For example, two items with different itemNo, itemName, and itemPrice, but with the same quantities could be considered equal. Besides, you wouldn't be able to change the comparison attribute without changing the equals() code every time.

Also, creating a custom contains() method makes no sense, since it belongs to the ArrayList class, and not to Item.

If you can use Java 8, a clean way to do it is to use the new Collection's removeIf method:

Suppose you have an Item class with the num and name properties:

class Item {
    final int num;
    final String name;

    Item(int num, String name) {
        this.num = num;
        this.name = name;
    }
}

Given a List<Item> called items and an int variable called number, representing the number of the item you want to remove, you could simply do:

items.removeIf(item -> item.num == number);

If you are unable to use Java 8, you can achieve this by using custom comparators, binary search, and dummy objects.

You can create a custom comparator for each attribute you need to look for. The comparator for num would look like this:

class ItemNumComparator implements Comparator<Item> {
    @Override
    public int compare(Item a, Item b) {
        return (a.num < b.num) ? -1 : ((a.num == b.num) ? 0 : 1);
    }
}

Then you can use the comparator to sort and search for the desired elements in your list:

public static void main(String[] args) {
    List<Item> items = new ArrayList<>();
    items.add(new Item(2, "ball"));
    items.add(new Item(5, "cow"));
    items.add(new Item(3, "gum"));

    Comparator<Item> itemNumComparator = new ItemNumComparator();
    Collections.sort(items, itemNumComparator);

    // Pass a dummy object containing only the relevant attribute to be searched
    int index = Collections.binarySearch(items, new Item(5, ""), itemNumComparator);
    Item removedItem = null;
    // binarySearch will return -1 if it does not find the element.
    if (index > -1) {
        // This will remove the element, Item(5, "cow") in this case, from the list
        removedItem = items.remove(index);
    }
    System.out.println(removedItem);
}

To search for another field like name, for example, you would need to create a name comparator and use it to sort and run the binary search on your list.

Note this solution has some drawbacks though. Unless you are completely sure that the list didn't change since the last sort, you must re-sort it before running the binarySearch() method. Otherwise, it may not be able to find the correct element. Sorting complexity is O(nlogn), so running it multiple times can get quite expensive depending on the size of your list.

like image 110
Anderson Vieira Avatar answered Oct 19 '22 17:10

Anderson Vieira


Do you want to remove an object at a specific index? I'm not entirely sure what you mean by 'number field'. If so, jump to method: remove(int):

http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#remove%28int%29

EDIT: If you want to find/adjust a field of an object in the Array list, you can do this (piece of my own code):

public boolean studentHasISBN(ArrayList<Student> st, String s){
    for(Student j : st) {
        if(s.equals(j.getRentedBookISBN()))
            return true;
    }
    return false;
}

All you have to do is iterate through the list, and search through the field that you want to find. Then use the remove(int) method.

like image 43
peter Avatar answered Oct 19 '22 18:10

peter