I have an inventory class that has an array of the class 'Item', called items. Within the Item class, I have an int called quantity to represent how many of the item that you get with each pickup. I haven't been able to figure out how to get the number of duplicate items within the array, so that I can multiply that by the getQuantity() method for that item and get the total quantity of the item that the player is carrying.
public class Inventory {
private Item[] items; //A private Item array, called items
private int firstFree;
private int quantity;
private WorldRenderer world;
/**
* CREATES THE INVENTORY AT A SIZE SPECIFIED IN THE PARATHENESIS
*/
public Inventory(int size) {
items = new Item[size];
firstFree = 0;
}
public int getItemCount() {
for (int i = firstFree; i < items.length; i++) {
if (items[i] != null) {
return items.length;
}
}
return 0;
}
public boolean add(Item item) {
if (firstFree == items.length) {
return false;
}
items[firstFree] = item;
for (int i = firstFree; i < items.length; i++)
if (items[i] == null) {
firstFree = i;
return true;
}
firstFree = items.length;
return true;
/**for (int i = 0; i < items.length; i++)
if (items[i] == null){
items[i] = item;
System.out.println("Item " + item.getName() + " added to inventory at index " + i); // TESTING
return true;
}
return false;
}**/
}
public Item get(int index) {
return items[index];
}
public void setQuantity(Item item, int quantity) {
for (int i = 0; i < items.length; i++) {
if (items[i] == item) {
items[i].setQuantity(quantity);
}
}
}
public void removeQuantity(Item item, int quantity) {
for (int i = 0; i < items.length; i++) {
if (items[i] == item) {
items[i].setQuantity(item.getQuantity() - quantity);
}
}
}
public int getQuantity(Item item) {
int quantity = 0;
for (int i = 0; i < items.length; i++) {
if (items[i] == item) {
quantity = items[i].getQuantity();
}
}
return quantity;
}
}
Perhaps there is a better way to go about creating an inventory for my particular problem?
EDIT:
Trying the HashMap and getting an NPE at this line
if (items.containsKey(item)){
Integer previousQuantity = items.get(items);
items.put(item, ++previousQuantity); // NPE this line.
} else {
items.put(item, 1);
}
Rather than Item[] items you might consider HashMap<Item, Integer> items where the Integer refers to quantity.
This would make sure that there are no duplicate Items as well as simplify finding the quantity.
Example:
import java.util.HashMap;
public class Inventory {
private HashMap<Item, Integer> items;
private int maxSize;
public Inventory(int maxSize) {
this.maxSize = maxSize;
items = new HashMap<Item, Integer>();
}
public int getItemCount() {
int count = 0;
for (Item item: items.keySet()){
count += items.get(item);
}
return count;
}
public boolean add(Item item) {
if (items.size() >= maxSize){
return false;
}
if (items.containsKey(item)){
Integer previousQuantity = items.get(items);
items.put(item, ++previousQuantity);
} else {
items.put(item, 1);
}
return true;
}
}
Generic Implementation of equals() and hashCode():
public class Item {
int itemType;
#Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
Item item = (Item) o;
if (itemType != item.itemType) { return false; }
return true;
}
#Override
public int hashCode() {
return itemType;
}
}
you can find out number of unique item by using Set. In Set no item is repeated. So if you can convert your array to set then you can find the number of unique item. And you can get the number of repeated item by subtracting from the total item.
to convet array to Set you have to do
Set<Integer> uniqueItem = new HashSet<Integer>(Arrays.asList(items));
int total_repeated_item=items.length-uniqueItem.size();
You probably need a unique ID to differentiate between items in you inventory, you can then put that in a Map which can just take care of counting duplicates for you . In your case the name of the item can be the unique identifier (Which would be the key in the Map)
.
Related
I have an ArrayList<Model> type and having fields id,name,isSelected and I have one HashMap which can store only selected items means if the item is clicked it will be stored in HashMap<Intere,Model>, Integer will be id , Model is that object which can be selected. I want to update Arraylist item field isSeleted to true which is present in hashmap. How can i do? I have tried many condition but nothing is working fine.
ArrayList<MainInterestModel> mainInterestList;
public static HashMap<Integer, MainInterestModel> mainIntrestHash = new HashMap<>();
Iterator myVeryOwnIterator = mainIntrestHash.keySet().iterator();
while (myVeryOwnIterator.hasNext()) {
int key = (int) myVeryOwnIterator.next();
MainInterestModel value = (MainInterestModel) mainIntrestHash.get(key);
int id = value.getId();
for (int i = 0; i < mainInterestList.size(); i++) {
MainInterestModel model = mainInterestList.get(i);
if (model.getId() == id) {
model.setSelected(true);
mainInterestList.set(i, model);
} else {
model.setSelected(false);
mainInterestList.set(i, model);
}
}
}
By Default isSelected is false but when the user will click that item will be stored in HashMap later i want to update selection so user interface will show selected items. HashMap has selected items and arraylist have all items but isSelected are false. at the time of showing selected items, I'm taking isSelected is true or not, which working fine, but arraylist update is not working.
My adapter class code
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
final MainInterestModel mainInterestModel = mainInterestModels.get(position);
holder.tvName.setText(mainInterestModel.getName());
holder.ivMainInterest.setImageResource(mainInterestModel.getImage());
// here isSelected is always false because in activity infalting adpter with arraylist, i want to setSeletced by hash object
boolean isSelected = mainInterestModel.isSelected();
if (isSelected) {
holder.ivMainInterest.setImageResource(R.drawable.bath_selector);
Log.e("Is Item selected ::", "" + mainInterestModel.getId());
} else {
holder.ivMainInterest.setImageResource(R.drawable.ic_bath);
Log.e("Is Item deselected ::", "" + mainInterestModel.getId());
}
holder.ivMainInterest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
boolean selection = mainInterestModel.isSelected();
if (selection) {
holder.ivMainInterest.setImageResource(R.drawable.ic_bath);
mainInterestModel.setSelected(false);
mainIntrestHash.remove(mainInterestModel.getId());
Log.e("After Remove SIZE:---", "" + mainIntrestHash.size());
} else {
mainInterestModel.setSelected(true);
holder.ivMainInterest.setImageResource(R.drawable.bath_selector);
mainIntrestHash.put(mainInterestModel.getId(), mainInterestModel);
Log.e("After Adding SIZE:---", "" + mainIntrestHash.size());
}
}
});
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
holder.ivMainInterest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
boolean selection = mainInterestModel.isSelected();
if (selection) {
holder.ivMainInterest.setImageResource(R.drawable.ic_bath);
mainInterestModel.setSelected(false);
} else {
mainInterestModel.setSelected(true);
holder.ivMainInterest.setImageResource(R.drawable.bath_selector);
}
notifyDataSetChanged();
}
});
}
remove hashmap and try to use this.
use this
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
public class ModelIterator {
public static void main(String arg[]) {
ArrayList<mainModel> mainmoldelList = new ArrayList<mainModel>();
for (int i = 1; i <= 3; i++) {
mainModel m = new mainModel();
m.setId(i);
m.setName("Rajendra" + i);
m.setSelected(false);
mainmoldelList.add(m);
}
mainModel m = new mainModel();
m.setId(0);
m.setName("Rajendra0");
m.setSelected(false);
HashMap<Integer, mainModel> mMap = new HashMap<Integer, mainModel>();
mMap.put(1, m);
Iterator<Entry<Integer, mainModel>> ite = mMap.entrySet().iterator();
while (ite.hasNext()) {
Map.Entry<Integer, mainModel> pair = (Map.Entry<Integer, mainModel>) ite
.next();
int key = pair.getKey();
mainModel mObj = (mainModel) mMap.get(key);
for (int i = 0; i < mainmoldelList.size(); i++) {
if (mainmoldelList.get(i).id == key) {
mainModel tmp = new mainModel();
tmp.setId(mainmoldelList.get(i).id);
tmp.setName(mainmoldelList.get(i).name);
tmp.setSelected(true);
mainmoldelList.add(tmp);
mainmoldelList.remove(i);
}
}
}
for (int i = 0; i < mainmoldelList.size(); i++) {
System.out.println(mainmoldelList.get(i).id + " "
+ mainmoldelList.get(i).name + " "
+ mainmoldelList.get(i).isSelected);
}
}
}
I have a custom hashtable implementation in java.
public class HashSet<T> implements HashTableInterface<T> {
private static int DEFAULT_ARRAY_SIZE = 10;
private T[] items;
public HashSet() {
final T[] items = (T[]) new Object[DEFAULT_ARRAY_SIZE];
this.items = items;
}
#Override
public boolean add(T item) {
int index = getIndex(item);
do {
if (items[index] != null) {
index = (index + 1) % DEFAULT_ARRAY_SIZE;
} else {
items[index] = item;
break;
}
} while (index != getIndex(item));
return true;
}
#Override
public boolean remove(T item) {
if (contains(item)) {
items[getIndex(item)] = null;
return true;
} else {
return false;
}
}
#Override
public boolean contains(T item) {
T itemArray = items[getIndex(item)];
if (item.equals(itemArray)) {
return true;
} else {
int index = (getIndex(item) + 1) % DEFAULT_ARRAY_SIZE;
do {
if (items[index] != null) {
if (items[index].equals(item)) {
return true;
} else {
index = (index + 1) % DEFAULT_ARRAY_SIZE;
}
} else {
break;
}
} while (index != getIndex(item));
}
return items[getIndex(item)] != null;
}
#Override
public int getIndex(T item) {
return item.hashCode() % DEFAULT_ARRAY_SIZE;
}
#Override
public int size() {
int count = 0;
for (T item : items) {
if (item != null) {
count++;
}
}
return count;
}
#Override
public String toString() {
return items.toString();
}}
In my add method I want to check if the place where the item would be stored is free, if not it should go to the next index. Until it finds an empty place.
My code works but I think, there could be a better way to do this.
public boolean add(T item) {
int index = getIndex(item);
do {
if (items[index] != null) {
index = (index + 1) % DEFAULT_ARRAY_SIZE;
} else {
items[index] = item;
break;
}
} while (index != getIndex(item));
return true;
}
I have the same problem in the contains method
public boolean contains(T item) {
T itemArray = items[getIndex(item)];
if (item.equals(itemArray)) {
return true;
} else {
int index = (getIndex(item) + 1) % DEFAULT_ARRAY_SIZE;
do {
if (items[index] != null) {
if (items[index].equals(item)) {
return true;
} else {
index = (index + 1) % DEFAULT_ARRAY_SIZE;
}
} else {
break;
}
} while (index != getIndex(item));
}
return items[getIndex(item)] != null;
}
There a many different ways to do collision avoidance, what you did is called "Linear Probing".
There is also (reference here)
Quadratic probing
Double hashing
And schemes that use linked lists for colliding values.
All of these have different tradeoffs which you should inform yourself on to make an informed decision.
I use following function to animate filtering a list (actually I once found that somewhere, don't know where anymore):
public void animateTo(List<T> items) {
applyAndAnimateRemovals(items);
applyAndAnimateAdditions(items);
applyAndAnimateMovedItems(items);
}
private void applyAndAnimateRemovals(List<T> newItems) {
for (int i = mListItems.size() - 1; i >= 0; i--) {
final T item = mListItems.get(i);
if (!newItems.contains(item)) {
removeItem(i);
}
}
}
private void applyAndAnimateAdditions(List<T> newItems) {
for (int i = 0, count = newItems.size(); i < count; i++) {
final T item = newItems.get(i);
if (!mListItems.contains(item)) {
addItem(i, item);
}
}
}
private void applyAndAnimateMovedItems(List<T> newItems) {
for (int toPosition = newItems.size() - 1; toPosition >= 0; toPosition--) {
final T item = newItems.get(toPosition);
final int fromPosition = mListItems.indexOf(item);
if (fromPosition >= 0 && fromPosition != toPosition) {
moveItem(fromPosition, toPosition);
}
}
}
public T removeItem(int position) {
final T item = mListItems.remove(position);
notifyItemRemoved(position);
return item;
}
public void addItem(int position, T item) {
mListItems.add(position, item); // <- EXCEPTION IS THROWN HERE
notifyItemInserted(position);
}
public void moveItem(int fromPosition, int toPosition) {
final T model = mListItems.remove(fromPosition);
mListItems.add(toPosition, model);
notifyItemMoved(fromPosition, toPosition);
}
Sometimes I get an exception like following in the addItem function:
java.lang.IndexOutOfBoundsException: Invalid index 203, size is 201
Actually, how can this happen? The loop in applyAndAnimateAdditions begins at 0, adds items one by one if they are not already in the list. How can the index exception occur?
You can add this to check if the position is equal or larger(>=) to the ArrayLists size just add the item to the end of the Arraylist.
public void addItem(int position, T item) {
if(position >= mListItems.size())
mListItems.add(mListItems.size()-1, item);
else
mListItems.add(position, item);
notifyItemInserted(position);
}
So here's your problem you are iterating through newItems but you are adding to mListItems
I'm trying to override a method that adds a string to a list. But i want the method to not add the string if the string is a duplicate in the list. If it isn't a duplicate than add if not do nothing. Here is my code. I'm just confused why it is not working.
public class Hw6 <T extends Comparable<? super T>> implements SortedListInterface<T>
{
private ListInterface<T> list;
public Hw6()
{
list = new LList<T>();
}
#Override
public boolean add(T newEntry) {
boolean results = false;
if(!contains(newEntry))
{
list.add(newEntry);
results = true;
}
return results;
}
public boolean addPrivate(T newEntry)
{
int newPosition = Math.abs(getPosition(newEntry));
return list.add(newPosition, newEntry);
}
#Override
public boolean remove(T anEntry) {
boolean result = false;
int position = getPosition(anEntry);
if (position > 0)
{
list.remove(position);
result = true;
}
return result;
}
#Override
public int getPosition(T anEntry) {
int position = 1;
int length = list.getLength();
while((position <= length) && (anEntry.compareTo(list.getEntry(position)) > 0))
{
position++;
}
if ((position > length) || (anEntry.compareTo(list.getEntry(position)) != 0))
{
position = -position;
}
return position;
}
#Override
public T getEntry(int givenPosition) {
return list.getEntry(givenPosition);
}
#Override
public boolean contains(T anEntry) {
boolean found = false;
for (int index = 0; !found && (index < getLength()); index++)
{
if (anEntry.equals(list.getEntry(index)))
found = true;
}
return found;
}
#Override
public int getLength() {
// TODO Auto-generated method stub
return list.getLength();
}
#Override
public boolean isEmpty() {
if(getLength() == 0)
return true;
else
return false;
}
#Override
public boolean isFull() {
return false;
}
public static void main(String args[])
{
LList<String> list = new LList<String>();
list.add("brad");
list.add("nick");
list.add("brad");
for(int i = 1; i <= list.getLength(); i++)
{
System.out.println(list.getEntry(i));
}
}
}
here is my output. i don't want it to add brad because its a duplicate
brad
nick
brad
It is because in your test you are creating a LList object but you should be creating a Hw6 object.
When adding the key it displays key added but then when I type inventory it says backpack empty, also when I go to use the item it wont let me, as its not usable.
public class Get extends AbstractCommand {
public Get (String name, String description){
super (name, description);
}
#Override
public void execute (Game game, String string) {
Item temp = game.getCurrentRoom().getItem(string);
UserInterface ui = game.getUI();
if(temp == null) ui.println("Item added\n");
else if (!(temp instanceof Moveable)) ui.println("item can not be moved");
else if (!game.getBackpack().add(temp)) ui.println("item can not be moved");
else game.getCurrentRoom().removeItem(temp);
}
}
#Override
public void execute(Game game, String string){
Item itemInBag = game.getBackpack().getItem(string);
Item itemInRoom = game.getCurrentRoom().getItem(string);
if(itemInBag!= null) {
if(itemInBag instanceof Useable){
game.setGameState(((Useable)itemInBag).use(game));
}else game.getUI().println("you can not use item");
}else if(itemInRoom!= null){
if(itemInRoom instanceof Useable){
game.setGameState(((Useable)itemInRoom).use(game));
}else game.getUI().println("this item can not be used");
}else {
game.getUI().println("take the item and use when you need to");
}
}
}
public class Inventory extends AbstractCommand {
public Inventory (String name, String description){
super (name, description);
}
#Override
public void execute (Game game, String string) {
if(((BackpackImpl)game.getBackpack()).getCount()==0) {
game.getUI().println("Backpack is empty");
}else {
for(Item i: game.getBackpack().getItems()) {
game.getUI().println(i.getName());
}
}
}
}
List<Item> items;
int maxCapacity;
public BackpackImpl (int maxCapacity){
this.maxCapacity = maxCapacity;
items = new ArrayList<Item>(5);
}
public BackpackImpl () {
this.maxCapacity = 5;
}
#Override
public boolean add(Item item){
if(items.size()>maxCapacity)
{System.out.println("your backpack canot fit no more\n");
return false;
}
items.add(item);
return true;
}
#Override
public Item remove(String string){
for(Item i: items){
if(((i.getName()).toLowerCase()).equals(string.toLowerCase())) {
items.remove(i);
return i;
}
}
return null;
}
#Override
public Item getItem(String string){
for(Item i: items){
if(((i.getName()).toLowerCase()).equals(string.toLowerCase())) {
return i;
}
}
return null;
}
#Override
public int getCapacity(){
return maxCapacity;
}
#Override
public List<Item> getItems(){
return items;
}
public int getCount (){
return items.size();
}
public void clear(){
items.clear();
}
}
Due to the "if/else (if)" construction in your Get.execute method, a new item is never added via the BackpackImpl.add() method.
Revise your Get.execute method and only print "Item added" when your code has actually called the BackpackImpl.add() method. Also, to keep your code readable, always use {} when using "if/else (if)" constructions. E.g.:
if (temp == null) {
ui.println("Item added\n");
} else if (!(temp instanceof Moveable || game.getBackpack().add(temp))) {
ui.println("item can not be moved");
} else {
game.getCurrentRoom().removeItem(temp);
}