How to use hashtable and bucket hashing - java

So recently I have been trying to practice with hashing and using linkedlists in a table to store values. I understand the concept but I am having trouble putting it into practice and can't seem to find what I'm looking for online.
For example:
Let's say I wanted to use a hashtable to store things like for a computer such as the monitor, mouse, etc. I would want methods such as:
boolean addMonitor(String id, String description, double price, int units, String size)
boolean addMouse(String id, String description, double price, int units, int buttons)
I don't understand how to use these methods to store them in a hashtable. I would obviously like to use other methods to access and change the values within each later too. Any help is appreciated. Thank you.

Even if its name says "table", HashTable is not like a "database table" where you have columns, and each column store values... it seems that you want use hashtable as a database table.
Hashtable store objects! So your methods should look better like this:
public class Example {
public static void main(String[] args) {
ItemStore store;
Monitor monitor;
Mouse mouse;
store = new ItemStore();
monitor = new Monitor();
monitor.id = 2;
monitor.price = 6;
mouse = new Mouse();
mouse.id = 7;
mouse.buttons = 3;
store.addItem(monitor);
store.addItem(mouse);
System.out.println(store.getItem(2).price); // = 6
System.out.println(((Monitor) store.getItem(2)).dpi);
System.out.println(((Mouse) store.getItem(7)).buttons); //Downcasting ... = 3
}
public static class Item {
String id;
String description;
int price;
// common attributes here!
}
public static class Monitor extends Item {
private int dpi;
// monitor particular atributes here!!
}
public static class Mouse extends Item {
private int buttons;
// mouse particular attributes here!!!
}
public static class ItemStore {
private Hashtable<String, Item> table = new HashTable<>();
public boolean addItem(Item item) {
this.table.put(item.getId(), item);
}
public Item getItem(String id) {
return this.table.get(id);
}
}
}

Related

deleting duplicates from array list

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() {
}
}
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).
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
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;
}
}
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);

What is the most efficient way to store and recall one object from either of two unique keys in Java?

I am working on creating a very performance-focused event-driven system. In this program, I have one object that needs to be linked to two different unique keys. The object contains parameters of what to do when one of two different events is triggered.
public class MonthConfiguration implements Comparable<MonthConfiguration>, Serializable {
final String monthID;
public final String displayID;
private final Double dte;
public boolean enabled;
...
public MonthConfiguration(String monthID, String displayID, boolean enabled, double dte) {
this.monthID = monthID;
this.displayID = displayID;
this.enabled = enabled;
this.dte = dte;
}
...
#Override
public int compareTo(MonthConfiguration o) {
return this.dte.compareTo(o.dte);
}
}
I currently need to quickly recall one of these objects in two different call backs that are triggered with unique keys
HashMap<String, MonthConfiguration> monthMap = new HashMap<>()
#Override
public void onEventOne(String key1) {
MonthConfiguration mon1 = monthMap.get(key1)
...
}
#Override
public void onEventTwo(String key2) {
MonthConfiguration mon2= monthMap.get(key2)
...
}
In the above example key1 != key2, however mon1 and mon2 are the same.
Currently I am using the code
MonthConfiguration mon = new MonthConfiguration (monthID, displayID,enabled, dte);
monthMap.put(key1, mon);
monthMap.put(key2, mon);
Is there a better way to do this? The number of MonthConfiguration objects is rather large and I am worried about the efficiency of this and possible memory leaks as objects are deleted/added to the map.

Java array list returning 0 value

I have created a class like this, which contains a bunch of arraylist as you can see. I've been setting the array with the methods add.. and then retrieving it with get.., when i tried to System.out.println numberofcitizen for example it is returning 0. Note that i have instantiated the class in another class to set the values.
public int numberOfCitizen;
private final ArrayList<Integer> citizenid = new ArrayList<>();
private final ArrayList<String> citizenName = new ArrayList<>();
private final ArrayList<Integer> citizenWaste = new ArrayList<>();
private final ArrayList<Float> longitude = new ArrayList<>();
private final ArrayList<Float> latitude = new ArrayList<>();
private final ArrayList<String> address = new ArrayList<>();
public void working() {
System.out.println("executing fine");
}
public void setnoOfcit(int number) {
this.numberOfCitizen = number;
}
public int getnumber() {
return this.numberOfCitizen;
}
public void addCitizenId(int citizen) {
citizenid.add(citizen);
}
public int getCitizenid(int i) {
int citId = citizenid.get(i);
return citId;
}
public void addCitizenName(String citizenname) {
citizenName.add(citizenname);
}
public String getCitizenName(int i) {
return citizenName.get(i);
}
public void addCitizenWaste(int waste) {
citizenWaste.add(waste);
}
public int getCitizenWaste(int i) {
return citizenWaste.get(i);
}
public void addLatitude(float lat) {
latitude.add(lat);
}
public float getLat(int i) {
return latitude.get(i);
}
public void addlng(float lng) {
longitude.add(lng);
}
public float getlng(int i) {
return longitude.get(i);
}
com.graphhopper.jsprit.core.problem.VehicleRoutingProblem.Builder vrpBuilder = com.graphhopper.jsprit.core.problem.VehicleRoutingProblem.Builder.newInstance();
public void runVPRSolver() {
System.out.println(numberOfCitizen);
System.out.println(getCitizenName(0));
//create a loop to fill parameters
Probable source of problem :
numberOfCitizen is a member attribute that you seem to never change. If you want it to represent the number of elements in your lists, either use citizenName.size() or increment the value of numberOfCitizen in one of the add methods.
Design flaw :
Your design takes for granted that your other class always use that one properly. Anytime you or someone uses that class, he must make sure that he add every single element manually. This adds code that could be grouped inside your class, which would be cleaner and easier to maintain.
So instead of several add method like this :
addCitizenid();
addCitizenName();
addCitizenWaste();
addLongitude();
addLatitude();
addAddress();
Design an other Citizen class which will contain those elements, and use a single list of instances of that class. That way you can use only one method :
private List<Citizen> citizenList = new ArrayList<>();
public void addCitizen(Citizen c) {
/*Add element in your list*/
citizenList.add(c);
}
This programming methodology is called "Encapsulation" which you can read about here
You need to increment numberOfCitizen in your add methods. For example:
public void addCitizenId(int citizen){
citizenid.add(citizen);
numberOfCitizen++;
}
I would also suggest encapsulating your variables into Objects, so create a citizen class:
public class Citizen {
private Integer id;
private Integer name;
private Integer waste;
}
And change your variable to an ArrayList of objects:
ArrayList<Citizen> citizens;

Choosing between `Collection <MyObject>` inside vs outside of `MyObject` class [Java]

What is the best way to store a Collection<MyItem> ? This collection is effectively static for current user. Each user can only see their collection. MyItem item implements IItem:
public interface IItem {
public Integer getItemID();
public void setItemID(Integer id);
public String getTitle();
public void setTitle(String title);
/*more getters and setters*/
public IItem parseServerResponse(String response);
public int postItem(); //posts this IItem to server, return ok ->200, unauth->401, etc
public IItem findItem(String[] filters);
/*more advanced methods*/
}
I can store Collection<MyItem> elsewhere, but then I can't access private MyItem methods from CurrentMyItems:
public class CurrentMyItems{
private final List<IItem> allItemsList;
public CurrentMyItems(String allItemsServerResponseString){
JSONArray rawItems = parseResponse(allItemsServerResponseString);
int arrSize = rawItems.length()+estimateQuantityOfNewItems();
List<IItem> allItemsList = new ArrayList<>(arrSize);
for (int i = 0; i < Items.length(); i++) {
allItems.add(i, parseItem(Items.get(i)));
}
}
/*methods*/
}
Or inside of the MyItem class (see commented out options):
public class MyItem implements IItem {
/*
private final static List<IItem> allItemsStaticList = new ArrayList<>();
private final static Map<Integer, IItem> allItemsStaticMap = new HashMap<>();
private final List<IItem> allItemsList; //
private final static Map<Integer, IItem> allItemsMap;
*/
/*implemented methods*/
}
allItemsStaticList - stores a static list of all Items. Seems memory efficient, but what if I need to store separate collections of MyItems in future? This is highly unlikely, but still...
allItemsList - Same class has two distinct functions. It is either
storing a single Item, in which case allItemsList/Map = null;
or
allItemsList = new ArrayList<>();, while other fields are empty.
This seems OK, but it breaks the Least Surprise Principle.
Which approach to store a MyItemCollection is more natural?
Also, should I store Items as a Map or a List given that MyItem myItem = getMyItemByID(int id); is the main way to access MyItem?
Update
We can implement an Item class so that an instance can either hold a collection of Item instances or the modeled data, but not both.
public class Item {
private final Map<Integer, Item> itemsMap;
private final IntegerProperty itemID; // private final String[] names;
public Item(){
itemsMap = new HashMap<>();
itemID = null; //names = null;
}
private Item(Integer id) {
itemsMap= null;
itemID = new SimpleIntegerProperty(id); //names = new String[1];
}
public Item makeGenericItem(){
return itemsMap == null ? null : new Item(itemsMap.size());
}
// other methods, including getters and setters
}
But at what cost?.. This class violates single responsibility principle.
Conclusion - in most cases a Collection of Item instances should be stored outside of Item class.
In OOP the data elements of an object are also known as attributes of the object. So, you should ask yourself whether a collection of items is an attribute of an item or not.
For example, when you assume your items are students. Would you say that a list of students is an attribute of a student? -- Probably not, as a list of students is not part of a student. Instead a student is part of a list of students.
Since a list of students is not an attribute of students in real life, I would not model it differently in code just to make it technically more elegant.
The design of your classes should be driven by the structure of the domain that your are working in. When you need to decide where to put an attribute do not ask "does it make sense to put it here because of the features my programming language offers?" but ask "where does this attribute belongs to in my domain?".

Adding subcategories to a java Enum

Suppose I have a simple Java Enum:
public Enum itemType
{
FRUITS("fru"),
VEGETABLES("veg"),
LIQUOURS("liq"),
SODAS("sod");
private String dbCode;
public ItemType(String dbCode){
this.dbCode = dbCode;
}
public String getDbCode(){
return this.dbCode;
}
}
I would now like to introduce a "category" to this enum, for example to make the distinction between liquid items and solid items. I found two ways of doing this within the enum class, see below. However, both suffer from the same anti-pattern: if the amount of categories or amount of items ever increases/decreases (imagine 100 item types with 10 categories!), I've got a lot of updating to do. What patterns can I use to design this enum as cleanly and re-usable as possible?
First approach: Add additional properties to the enum
public Enum itemType
{
FRUITS("fru",false),
VEGETABLES("veg",false),
LIQUOURS("liq",true),
SODAS("sod",true);
private String dbCode;
private boolean liquid;
public ItemType(String dbCode, boolean liquid){
this.dbCode = dbCode;
this.liquid = liquid;
}
public String getDbCode(){
return this.dbCode;
}
public boolean isLiquid(){
return this.liquid;
}
}
Second approach: Use static methods to ask about subcategories
public Enum itemType
{
FRUITS("fru"),
VEGETABLES("veg"),
LIQUOURS("liq"),
SODAS("sod");
private String dbCode;
public ItemType(String dbCode){
this.dbCode = dbCode;
}
public String getDbCode(){
return this.dbCode;
}
public static boolean isLiquid(ItemType type){
switch(t){
case SODA:
case LIQOURS: return true;
default: return false;
}
}
How about using an EnumSet for that?
public enum ItemType
{
FRUITS("fru"),
VEGETABLES("veg"),
LIQUOURS("liq"),
SODAS("sod");
public static final EnumSet<ItemType> LIQUIDS = EnumSet.of(LIQUOURS, SODAS);
// ...
}
Then you can use ItemType.LIQUIDS.contains(someItemType) to check if someItemType is a "liquid".
I would do something like:
enum Category {
LIQUID, SOLID;
}
enum ItemType {
FRUITS("fru", SOLID),
VEGETABLES("veg", SOLID),
LIQUOURS("liq", LIQUID),
SODAS("sod", LIQUID);
private String dbCode;
private Category category;
public ItemType(String dbCode, Category category){
this.dbCode = dbCode;
this.category = category;
}
/* getters / setters */
}
That would allow, for example, that you can add new products and categories (e.g. BUTANE("but", GAS)) without having to modify the existing code (as would happen in Approach 2).
On the other hand, if the number of categories and items is long and changing, I would consider to use a SQL database.
Since you are modeling something that has no logic that can be encoded in an algorithmic way (i.e. there's no algorithm that would figure out that "sod" is liquid and "veg" is not) there is no way around enumerating all related pairs of (item, category) in one way or the other.
There are three approaches to implementing it:
Enumerate categories on item's side - this is what your code does in both cases, or
Enumerate items on category's side - this would build an enum of categories, and attach a full list of items to each of them, or
Enumerate item+category pairs independently - this approach may be useful when storing item/category mapping in the database or in a configuration file.
I would recommend taking the third approach as it is the most "symmetric" one. Make a table for categories with category codes, and add a "cross-table" (or a cross-file) that has all pairs of categories and their corresponding items. Read the cross table/file at startup, and set up the dependencies on both sides.
public Enum ItemType {
FRUITS("fru")
, VEGETABLES("veg")
, LIQUOURS("liq")
, SODAS("sod");
public void addCategory(ItemCategory category) ...;
public EnumSet<ItemCategory> getItemCategories() ...;
}
public Enum ItemCategory {
LIQUIDS("liq")
, SNACKS("snk")
, FAST("fst");
public void addItem(ItemType type) ...;
public EnumSet<ItemType> getItemTypes() ...;
}
Cross-file or cross-table may look like this:
liq liq
sod liq
fru snk
fru fst
sod fst
You process it by enumerating pairs, and calling addCategory on the pair's item side, and calling addItem on the pair's category side.
These were three excellent answers, but I think I can combine all three in one nice package:
public enum ItemType {
FRUITS("fru",PERISHABLE),
VEGETABLES("veg",PERISHABLE),
LIQUOURS("liq",LIQUIDS),
SODAS("sod",LIQUIDS),
FRESH_SQUEEZED_ORANGE_JUICE("orgj",LIQUIDS,PERISHABLE);
private final String dbCode;
private final EnumSet<ItemCategory> categories;
private static final Map<ItemCategory,Set<ItemType>> INDEX_BY_CATEGORY = new EnumMap<>(ItemCategory.class);
ItemType(String dbcode,ItemCategory... categories) {
this.dbCode = dbcode;
this.categories = EnumSet.copyOf(Arrays.asList(categories));
//for (ItemCategory c:categories) {
// // Illegal Reference to Static Field!
// INDEX_BY_CATEGORY.put(c, this);
//}
}
static {
for (ItemCategory c:ItemCategory.values()) {
INDEX_BY_CATEGORY.put(c, EnumSet.noneOf(ItemType.class));
}
for (ItemType t:values()) {
for (ItemCategory c:t.categories) {
INDEX_BY_CATEGORY.get(c).add(t);
}
}
}
public boolean is(ItemCategory c) {
return INDEX_BY_CATEGORY.get(c).contains(this);
}
public Set<ItemType> getAll(ItemCategory c) {
return EnumSet.copyOf(INDEX_BY_CATEGORY.get(c));
}
public String getDbCode() {
return dbCode;
}
}
Now,
we can easily ask about additional subcategories without writing the code for it: boolean isVegetableLiquid = VEGETABLES.is(LIQUIDS);
we can easily assign not only one, but multiple categories to an item as you can see for FRESH_SQUEEZED_ORANGE_JUICE.
we are using EnumSet and EnumMap for performance, including their methods like contains.
we absolutely are minimizing the amount of code required to add an additional item. This could be further minimized by setting this up by database or configuration. However, in that case we would have to avoid the use of Enum as well.

Categories

Resources