I have a set of objects of type "Part" and each Part is associated with quantity(a field that specifies number of units required of that particular Part ). Is there in way in java to store this data, other than hash map?
You can write a wrapper object that has two fields, Part and quantity:
public class PartWithQuantity
{
private Part part;
private int quantity;
public int getQuantity() { return quantity; }
public void setQuantity(int q) { quantity = q; }
public Part getPart() { return part; }
public void setPart(Part p) { part = p; }
}
You can also use a TreeMap if the concern is that the HashMap might use too much memory.
This can be done very easily by just storing the metadata into the arraylist.
You can take a class that contains one reference of part type and other(quantity) is int type. Then you can even store the instances of this new class into an arraylist. Do Remember ,you can access your information anytime from this arraylist by calling the object.
The simplest way to achieve this would be to modify the Part class and add the quantity field, along with its setter and getter.
Another option would be to use a wrapper object and store it in the Set.
I have created a convenience method called check() to easily identify the Part of interest:
public class PartExtended {
private Part part;
private int quantity;
public PartExtended(Part part, int quantity) {
this.part = part;
this.quantity = quantity;
}
public boolean check(Part part) {
return part.equals(this.part);
}
public Part getPart() {
return part;
}
public int getQuantity() {
return quantity;
}
}
To retrieve a Part's quantity, use a for loop:
Set<PartExtended> data = new HashSet<>();
data.add(new PartExtended(new Part(), 0));
for (PartExtended item : data) {
if (item.check(new Part())) {
int quantity = item.getQuantity();
}
}
Related
I have an application which is using Drools Expert to evaluate some rules. The results will be of this type:
String, String, Integer
A typical result example is:
"Rule 1", "RED", 1
"Rule 2", "AMBER", 2
"Rule 3", "GREEN", 1
"Rule 4", "INFO", 3
The first element is a key. So I am thinking of using a Map structure. The last field is an integer specified via an enum. I want to be able to pick from this list of results the rule with the maximum priority (which is the last field).
What is the best way to structure this in terms of using the Java collections library? Is the Map the best?
I want to be able to pick from this list of results the rule with the maximum priority (which is the last field).
You could package the data into a class that is comparable based on the last field, and then use a PriorityQueue.
class Data implements Comparable<Data> {
private String rule;
private String other;
private int priority;
...
#Override
public int compareTo(Data other) {
return Integer.compare(priority, other.priority);
}
}
Now, you can use a PriorityQueue<Data>.
Queue<Result> resultList = new PriorityQueue<Result>();
public class Result implements Comparable<Result>{
private String ruleText;
private String text; // 2. value
private int priority;
#Override
public int compareTo(Result result) {
return new Integer(priority).compareTo(result.getPriority());
}
public String getRuleText() {
return ruleText;
}
public void setRuleText(String ruleText) {
this.ruleText = ruleText;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
}
Yes Map are the best to store if you have something termed as key in your data collection. For prioritization, its best to use PriorityQueue.
The best way would be to create an Object implementing comparable.
class Rule implements Comparable<Rule>{
String firstPart;
String secondPart;
int priority;
//constructor
//getters and setters
#Override
public int compareTo(Rule other){
return Integer.compare(this.priority, other.priority);
}
}
Then you just put them all in a TreeSet<Rule> and iterate on it, they will come out sorted. Or you can store them in list and call Collections.sort(list).
The answer to this will probably turn out to be obvious in retrospect but for now I find myself rather stuck on this. I'll give some blocks of code first and then present the problem.
This is part of my class Stockmanager, I have omitted some methods that have nothing to do with this problem.
import java.util.ArrayList;
public class StockManager
{
private ArrayList stock;
public StockManager()
{
stock = new ArrayList();
}
public void addProduct(Product item)
{
stock.add(item);
}
public Product findProduct(int id)
{
int index = 0;
while (index < stock.size())
{
Product test = stock.get(index);
if (test.getID() == id)
{
return stock.get(index);
}
index++;
}
return null;
}
public void printProductDetails()
{
int index = 0;
while (index < stock.size())
{
System.out.println(stock.get(index).toString());
index++;
}
}
}
Here's my class Product, again with some methods omitted.
public class Product
{
private int id;
private String name;
private int quantity;
public Product(int id, String name)
{
this.id = id;
this.name = name;
quantity = 0;
}
public int getID()
{
return id;
}
public String getName()
{
return name;
}
public int getQuantity()
{
return quantity;
}
public String toString()
{
return id + ": " +
name +
" voorraad: " + quantity;
}
}
My problem lies in the fact that I get a compile time error in the findProduct() method. To be more specific the line Product test = stock.get(index); is indicated with a message incompatible types.
The constructor of StockManager creates a new ArrayList with the name stock. As is evident from the method addProduct() this ArrayList contains items of the type Product. The Product class has a number of variables one of which is called id and is of type integer. That class also contains a method getID() that returns an id.
As far as I know, the way of getting an item from an arraylist is the get() method with the number between the () indicating the item's position. Seeing as my arraylist contains instances of Product, I expect to get a Product as result when I use the get() method on the arraylist. So I don't understand why it doesn't work when I define a variable called test of the type Product and try to assign an item from the arraylist to it. I have as far as I know, successfully used this same technique in the method printProductDetails() where I use the toString() method from Product on the object from the arraylist.
I hope someone will be able to clarify for me where I am at fault. If it makes any difference, I am doing this stuff in BlueJ which is probably not the best tool for it but it is the one I'm supposed to use for this school project.
private ArrayList stock;
You should redeclare this with a bounded type like so:
private List<Product> stock = new ArrayList<Product>();
If you don't, this line:
Product test = stock.get(index);
won't work because you're trying to assign a raw Object to a Product.
Others have suggested casting the Object to a Product, but I wouldn't recommend this.
Your stock is defined as private ArrayList stock, which means that stock.get() returns an Object without any special type. You should either make Stock an ArrayList of Products
ArrayList<Product> stock;
or cast the result of the get method manually
Product test = (Product)stock.get(whatever);
Product test = (Product) stock.get(index);
or if you make your list List<Product> stock your line should work without changes.
I am trying to implement a solution (in Java 1.6) where i need to store some values (for a set of properties) and thinking in three options considering the following three (Any other idea is of course wellcome!)
Option 1
Create a class (call it Property) that can store different type of objects (String, int, boolean...) and and work with the set of properties as a List<Property>
Something like:
private String type; //Store the type of Object
private String name; //Store the name of the property
private String valueStr; //Store the String value
private int valueInt; //Store the int value
private boolean valueBool; //Store the boolean value
I dont really like the idea of having many properties and using only one of them. (only one of the values will be set per property)
Option 2
Use HashMap<String, Object> and parse the type on each case.
Have the good thing that you can get the Property by name
Option 3
Use HashMap<String, Property> Where the String is the name of the property and you can get the value with the name and no need to parse.
Questions are:
Which of one you think is the best one?
or if none of them are good i would like to hear other ideas
Also is there any performance difference between the List and the HashMap?
Thanks in advance for the help.
I think better is to have a custom Value class like this:
public class MyValue {
enum Type {
INT, STRING, BOOL;
}
private Type type; //Store the type of Object in Type Enum
private Object value; //Store the value in Object
public void setValue(int val) {
type = Type.INT;
value = new Integer(val);
}
public void setValue(String val) {
type = Type.STRING;
value = val;
}
public void setValue(boolean val) {
type = Type.BOOL;
value = new Boolean(val);
}
public String stringVal() {
// check type to be STRING first
return (String) value;
}
public int intVal() {
// check type to be INT first
return ((Integer) value.intValue());
}
public boolean booleanVal() {
// check type to be BOOL first
return ((Boolean) value.booleanValue());
}
}
You will need to convert from Object to specific type based on enum Type in your getters.
Another option would be something like this, using inheritance rather than keeping a large number of unused fields around.
public interface Property {
String getType();
String getName();
Object getValue();
}
public abstract class AbstractProperty implements Property {
private final String name;
protected AbstractProperty(String name) {
this.name = name;
}
}
public class StringProperty extends AbstractProperty {
private final String value;
public StringProperty(String name, String value) {
super(name);
this.value = value;
}
#Override
public String getType() {
return String.class.getName();
}
#Override
public String getValue() {
return value;
}
}
public class IntegerProperty extends AbstractProperty {
private final Integer value;
public IntegerProperty(String name, Integer value) {
super(name);
this.value = value;
}
#Override
public String getType() {
return Integer.TYPE.getName();
}
#Override
public Integer getValue() {
return value;
}
}
I think option 2 would be the best for you. Considering that you are storing properties I am expecting that you would be querying this list quite often which again points in the direction of a HashMap as that would make your lookup very efficient.
I suggest using an enum instead. Enums are good for holding lists of values, and are effective at retrieval.
public enum Property {
TYPE,
NAME,
VALUEINT; //...
private String sProp = "";
private int iProp = 0;
private boolean bProp = false;
public String getStringProp() {return sProp;}
public int getIntProp() {return iProp;}
public boolean getBoolProp() {return bProp;}
public void setStringProp(String str) {this.sProp = str;}
public void setIntProp(int i) {this.iProp = i;}
public void setBoolProp(boolean b) {this.bProp = b;}
}
This can then be accessed with Property.TYPE, Property.VALUEINT, etc. You can set properties with Property.TYPE.setStringProp(), and get them with Property.TYPE.getStringProp().
You can read more about enums from Oracle's site.
I am unsure if there's one 'best' way. It really depends on how the data would be used after storing in a data structure.
In cases when I just need to accumulate properties and do something on each of them, I'd use a list, or even an array, sometimes.
If you might have to get a particular property, say by name, then a HashMap could help.
Again if you want to use the native object type or an instance of Property depends on what kind of data you have.
Which performs better depends on the number of objects you have, how you'd access them for use, how often you'd insert and several other factors.
I ran into following situation and I am wondering about best solution. Let's say I have List<Object1> and List<Object2>, these lists are result of two separated queries. Both of them have the same size and there is relationship 1:1 between elements in the lists based on ID. I know that best solution would be fetching data in one DB query but that's possible right now.
So my question is, what is the best way to join these lists into let's say List<Object3>?
I would
convert the first list into Map with key as the ID and value as Object1.
iterate through the second list, get the object1 corresponding to the ID of object2.
perform the merge operation or whatever is intended and prepare object3 and put it in a list.
The resultant order would be that of in second list.
Make sure the queries order by id and then just iterate over the lists at the same time, whilst creating your new super list. This isn't foolproof, if the queries return differing sets of ids then the data will be corrupt. You could always add a check to make sure the ids match before adding the two objects to the super list though.
Use Apache Common BeanUtils as you don't have to write much code, also datatype convertions will be proper.
In this case both object1List and object2List should be in same order based on ID. To have that use Comparable interface to sort these based on ID for both Object1 and Object2
Example Code
Object1.java
public class Object1 implements Comparable<Object1>{
private Integer id;
private String name;
private int quantity;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public int compareTo(Object1 compareObject1) {
int compareId = ((Object1) compareObject1).getId();
//ascending order
return this.id - compareId;
}
}
Object2.java
public class Object2 implements Comparable<Object2>{
private Integer id;
private double amount ;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public int compareTo(Object2 compareObject2) {
int compareId = ((Object2) compareObject2).getId();
//ascending order
return this.id - compareId;
}
}
Object3.java which will have fields names same as Object1 and Object2.java
Actual Implementation
int cnt = 0;
List<Object3> object3List = new ArrayList<Object3>();
List<Object1> object1List = Collections.sort(object1List);
List<Object2> object2List = Collections.sort(object2List);
for(Object1 obj1 : object1List) {
BeanUtils.copyProperties(obj3, obj1);
Object2 obj2 = object2List.get(cnt);
BeanUtils.copyProperties(obj3, obj2);
object3List.add(obj3);
cnt ++;
}
I would use a BidiMap (see Apache Commons Collections).
Moreover, if you're sure the two lists have the same size and each id is present within the two lists, you could sort the list by the id and go through them with a classic for loop.
Comparator<YourObject> comparator = new Comparator<YourObject>() {
#Override
public int compare(YourObject o1, YourObject o2) {
return o1.getId().compareTo(o2.getId());
}
};
Collections.sort(list1, comparator);
Collections.sort(list2, comparator);
// import org.apache.commons.collections.BidiMap;
// import org.apache.commons.collections.bidimap.DualHashBidiMap;
BidiMap map = new DualHashBidiMap();
// required: list1.size() == list2.size()
for (int i = 0; i < list1.size(); i++) {
map.put(list1.get(i), list2.get(i));
}
If equals and hashCode are using the ID, and they should if this represents the uniqueness in your objects, you could also use sets instead of lists. This way you will be able to do something like set1.addAll(set2)
public class Item {
/**
* Instance variables for this class
*/
private String itemName;
private int itemQuantity;
/**
* Contructor for this class
*/
public Item (String itemName, int itemQuantity) {
this.itemName = itemName;
this.itemQuantity = itemQuantity;
}
//setter and getter methods
public String getItemName () {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public int getItemQuantity () {
return itemQuantity;
}
public void setItemQuantity(int itemQuantity) {
this.itemQuantity = itemQuantity;
}
}
Ok..I already have the class for item. Now I have to write the CartItem class. The description that was given are as follows:
class CartItem{
/*
Objects of this class are used to hold items that the shopper purchases in the super market.
There are two attributes in this class, an item (an object created from the Item class) and a quantity (the number of that item that the shopper purchases). You have to write these two attributes. Note that one of the two will have a user defined data type.
*/
}
public class CartItem {
private Item item; //item from the item class
private int itemQuantity; //quantity how much shopper buys
public CartItem(Item itemName, int itemQuantity) {
this.getItem();
this.getQuantity();
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public int getQuantity() {
return itemQuantity;
}
public void setQuantity(int quantity) {
this.itemQuantity = itemQuantity;
}
}
Just wondering if it's correct though.
No, it's not correct. Look at your constructor:
public CartItem(Item itemName, int itemQuantity) {
this.getItem();
this.getQuantity();
}
Here you're calling the getters and completely ignoring the values the caller has passed in. I don't think you want to do that... think about what the constructor needs to do in order to populate the newly constructed object...
(You should also consider making these classes immutable, but that's a slightly different matter.)
Few things.
1 Person may shop more than one Item so have List of Item
2 Constructor isn't correct, which should be
public CartItem(Item itemName, int itemQuantity) {
this.item = itemName;
this.itemQuantity = itemQuantity;
}
No it's not.
The constructor for CartItem just calls this.getItem() and this.getQuantity(). This will just call the methods, which will obviously return null, since the attributes are never initialized. It should be:
public CartItem(Item itemName, int itemQuantity) {
this.item = itemName;
this.itemQuantity = itemQUantity;
}
Another problem is that you add getters and setters for all the fields, without even knowing if those methods are necessary. Try to favor immutability, and only provide setters if they are absolutely necessary. I won't explain all the advantages of immutability, because it would be too early given what you already know. But a good rule of thumb is : don't add a method to a class if it's not used.