Home > database >  deleting duplicates from array list
deleting duplicates from array list

Time:12-18

I'm creating a simple RPG console game, I'm at the stage of creating an inventory and loot system. Present in the program, both class Player and class Monster have the arrayList Backpack properties, when the program creates an object of the monster class, items in the monster's backpack are also automatically created, after killing the monster, you can take them to your backpack, and this is where my problem begins how to elegantly prevent duplication of items in the backpack, each item is a class too, now this function works by checking in a nested loop each item one by one to see if it is already in the backpack if it is instead of adding it once moreover, it increases its amount property, if I don't have this item in my backpack, it just adds to the list, the solution works, but definitely it is not the right solution, because with many of items this checking mechanism will grow a lot, if anyone has any valuable tips I will be grateful. I also have a second idea to create a boolean Is_it_in_Backpack variable, and somehow connect it with the loot collecting mechanism

Below some code sample

public class Player  {
public static ArrayList<Item> Backpack = new ArrayList<>()
}

and the class Skieleton:

public class Skieleton extends Monsters {

  public static ArrayList<Item> Backpack;

  public Skieleton() {
       Backpack = new ArrayList<>();
       Backpack.add(new Weapon("Rusty sword", "Just a rusty sword", 3, 2 ));
       Backpack.add(new Armor("Leather Armor", "Old leather armor", 6, 3));
    }

class item:

public class Item {

    public String ItemName;
    public String Description;
    public int ItemSize;
    public int ItemWeight;
    public int Amount;

    public Item(String ItemName, String Description, int ItemSize, int ItemWeight)
    {
        this.ItemName = ItemName;
        this.Description = Description;
        this.ItemSize = ItemSize;
        this.ItemWeight = ItemWeight;
    }

    public Item() {
    }
}

CodePudding user response:

I recommend you use a class that extends java.util.Set:

  • If order is not important for you, you can use HashSet;
  • If order of insertion is important, you can use LinkedHashSet;
  • If natural order is important (alphabetical by name or other property), you can use TreeSet and implement the interface Comparable onto the class inserted in the collection.

However, regardless of your choice, it's recommended you implement hashCode() (for optimization) and equals() (to let collection identify which item is equal to other and avoid duplication).

CodePudding user response:

If you can use third party libraries, I'd recommend using a Bag from Eclipse Collections.

With your Item class implementing equals and hashCode on ItemName field, your example usage could look like:


final MutableBag<Item> backPack = new HashBag<>();

final Item rustySword = new Item("Rusty sword", "Just a rusty sword", 3, 2);
final Item leatherArmour = new Item("Leather Armor", "Old leather armor", 6, 3);
     
backPack.add(rustySword);
backPack.add(leatherArmour);
backPack.add(rustySword);

System.out.println(backPack.toMapOfItemToCount());     // prints {Item[ItemName='Rusty sword']=2, Item[ItemName='Leather Armor']=1}
System.out.println(backPack.occurrencesOf(rustySword));  // prints 2

The API is rich, and provides a lot more: https://www.eclipse.org/collections/javadoc/11.0.0/org/eclipse/collections/api/bag/Bag.html

CodePudding user response:

I would use a Map.

Here's my suggestion:

 import java.util.*;

 class Player  {
    public Backpack backpack= new Backpack();
}

class Monster { }

 class Skieleton extends Monster {

  public Backpack backpack= new Backpack();

  public Skieleton() {
       
       backpack.add(new Weapon("Rusty sword", "Just a rusty sword", 3, 2 ));
       backpack.add(new Armor("Leather Armor", "Old leather armor", 6, 3));
    }
}

class Backpack {
    private HashMap<Item,Item> items = new HashMap<>();
    
    public Item add(Item item){
        if (items.containsKey(item)){
            items.get(item).Amount=  item.Amount;
            return items.get(item);
        } else {
            items.put(item,item);
            return item;
        }
    }
    
    public Item get(Item item){
        return items.getOrDefault(item, null);
    }
}
class Item {

    public String ItemName;
    public String Description;
    public int ItemSize;
    public int ItemWeight;
    public int Amount;

    public Item(String ItemName, String Description, int ItemSize, int ItemWeight)
    {
        this.ItemName = ItemName;
        this.Description = Description;
        this.ItemSize = ItemSize;
        this.ItemWeight = ItemWeight;
    }

    public Item() {
    }
    
    public boolean equals(Object o){
        if (o instanceof Item){
            return ItemName.equals( ((Item)o).ItemName);
        }
        return false;
    }
}

CodePudding user response:

You can use a HashMap for storing the items. First, I would like to change the Item class to not have amount field in it. Let an item denote what an item is (name, description, size and weight).

Here's the updated backpack:

Map<Item, Integer> backpack = new HashMap<>();

To add an item, you can use Map#merge method.

public void addItemToBackpack(Item item, int quantity) {
    backpack.merge(item, quantity, (oldQuantity, newQuantity) -> oldQuantity   newQuantity);
}

We insert the item and its quantity. If the item is not already present, it will be inserted with the passed quantity.

If it is already present, then the BiFunction which is a mapping function will be called with the existing value (oldQuantity) and the new value which we tried to insert (newQuantity). We sum them both, return it and the item's value (quantity) will be updated with this value.

Using method references, we can write the above as,

backpack.merge(item, quantity, Integer::sum);
  • Related