Only Allow Objects with Unique Name - Java - java

I am making an inventory system.
I want to ensure that objects I am creating (Ingredients) all have unique names. In other words, I want to make sure that there are never two Ingredients that have the same name in the whole program. Currently I have the following class:
package ingredient;
import java.util.HashSet;
public class Ingredient {
private final String name;
private final double price;
private static HashSet<String> names = new HashSet<String> ();
private Ingredient(String ingr_name, double ingr_price) {
name = ingr_name;
price = ingr_price;
}
public static Ingredient createIngredient(String ingr_name, double ingr_price) {
if (names.contains(ingr_name)) {
return null;
} else {
names.add(ingr_name);
return new Ingredient(ingr_name, ingr_price);
}
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
Then, when I go to actually make new ingredients, I make statements such as :
Ingredient egg = Ingredient.createIngredient("egg", 1);
Is this okay design? I suppose I am concerned because returning "NULL" might not be the best practice here.

I cant comment, but whatever...
I would go about this by storing all of the Ingredients in a different class, then you wouldn't need all this static nonsense. In the class where you actually create a new Ingredient (Ingredient egg = Ingredient.createIngredient("egg", 1);) you could maybe create an ArrayList of ingredients like so:
ArrayList<Ingredient> ingredients = new ArrayList<>();
Then when you make a new Ingredient you would just have to make sure you add it to the ArrayListand when you do so, check that none of the ingredients are already there, maybe something like this:
createIngredient("egg", 1);
or
Ingredient egg = createIngredient("egg", 1);
...
private Ingredient createIngredient(String ingr_name, double ingr_price){
for(Ingredient i : ingredients){
if(i.getName().equals(ingr_name)){
return null;
}
}
Ingredient newing = new Ingredient(ingr_name, ingr_price);
ingredients.add(newing);
return newing;
}
Then the Ingredient class could be cut down to something like this:
package ingredient;
public class Ingredient {
private final String name;
private final double price;
public Ingredient(String ingr_name, double ingr_price) {
name = ingr_name;
price = ingr_price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
And then you could access each individual Ingredientwith a method to run through the ArrayList and find the Ingredient with the name your looking for:
public Ingredient findIngredient(String name){
for(Ingredient i : ingredients){
if(i.getName().equals(name)){
return i;
}
}
return null;
}

I would recommend either
A) returning the already created ingredient
Or if that would confuse the caller,
B) throwing an exception
This can be a simple IllegalArgumentsException, or depending on your needs, a custom exception class.

Related

Multiple products in a single client(arrayList)

I've been asked to program a small online sales aplication.
It sounds very simple in theory (but it's been a hell for me). I'm just supposed to have an arrayList with about 5 products and then have a client buy 1 to 5 products and print the sales total.
public class Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public String printInfo() {
return "Product: " + name + " Cost: " + price;
}
}
Then I have a client class:
public class Cliente {
private String name;
private int numPedido;
ArrayList<Producto> products = new ArrayList<Producto>();
public void listBuilder() {
Producto shirt = new Producto("Shirt", 30);
Producto tshirt = new Producto("T-Shirt", 40);
Producto sweater = new Producto("Sweater", 50);
}
public Cliente(String name, int numPedido) {
this.name = name;
this.numPedido = numPedido;
}
public Cliente() {
}
public String getName() {
return name;
}
public int getNumPedido() {
return (int) (Math.random() * 100);
}
public void addNewClient() {
name = JOptionPane.showInputDialog("Nombre: ");
}
public String printInfo() {
return "Nombre: " + name;
}
}
Right now I'm stuck thinking on how to make a client select a product and get that attached to him. I was thinking on making an arrayList of an arrayList but I'm sure that would complicate things. I know there is probably an easier way to connect them but I can't think of any. The option I have in mind is a method which shows numbers from 1 to 3(corresponding to each product) and when the user picks one it should return the price of the item.
Still not sure how to implement it in a way that the user can pick multiple products.
EDIT:
I also have an admin class that goes like this:
public class Admin {
private Client[] clientList;
public AdminPedidos() {
clientList = new Client[2];
}
public void AddContact() {
clienteList[0] = addProduct();
clienteList[1] = addProduct();
fillList();
}
public Cliente addProduct() {
String contactoString = JOptionPane.showInputDialog("Are you a new client? Press 1 if yes.");
if (contactoString.equals("1")) {
return new Cliente();
} else {
return new Cliente(); //just for testing
}
}
private void fillList() {
for (Client i : clientList) {
i.addNewClient();
}
}
public void printContact() {
for (Client i : clientList) {
System.out.println(i.printInfo());
}
}
}
You can have some purchaseProduct method attached to each Client.
public void purchaseProduct(Product product) { this.products.add(product); }
Then each Client you instantiate (Client client = new Client(name, id);) can add Products to his/her cart with the purchaseProduct method.
I'm assuming you are using some kind of user input method (Scanner). With that you can read the user's input of which Product they want and accordingly call the function with the right Product.
The listBuilder function doesn't quite make sense to me btw (and after your edit, it's really hard to make sense of what the Admin class should be/represent).
Edit: You would probably want to create an ArrayList<Product> which will be attached to each client, which you already have. I sense that you have a difficulty deciding where to put your actual Products. You should not put them inside your Client class for sure.
You should think about who/where they are going to be used. Probably in main right? So just instantiate them there first and then the Client could choose which one to purchase (via the method I introduced before):
client.purchaseProduct(product);

Create an object that holds objects?

I am attempting to create an inventory tracking system. I have a class (in Java) called "InventoryItem" with the properties of name and quantity.
This works fine for simple objects, but what if my inventory item contains other inventory items, for example, a server with RAM?
Should I be creating my own datatype, or is there a better way to do this (linked listed maybe)? should my class extend whatever that datatype is or should I not bother creating my own class?
My class so far:
public class InventoryItem {
private String name;
private int quantity;
private InventoryItem childInventoryItem;
// CONSTRUCTORS
public InventoryItem() {
}
public InventoryItem(int quantity, String name) {
this.quantity = quantity;
this.name = name;
}
//GETTERS
public String getName() {
return name;
}
public int getQuantity() {
return quantity;
}
//SETTERS
public void setName(String name) {
this.name = name;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
A tree is usually what is involved in any parent-child relationship. If you aren't doing anything complicated, you can simply maintain an internal list that is basically List<InventoryItem> which contains any child items.
So all you would add to your class is something like this:
public class InventoryItem {
...
private List<InventoryItem> composingItems = new ArrayList<>(); //if still using Java 6 this must be new ArrayList<InventoryItem>();
...
public void addComposingItem(InventoryItem composingItem) {
composingItems.add(composingItems);
}
public List<InventoryItem> getComposingItems() {
//Enforce immutability so no one can mess with the collection. However
//this doesn't guarantee immutability for the objects inside the list;
//you will have to enforce that yourself.
return Collections.umodifiableList(composingItems);
}
}
There are many ways you can do this. I think the easiest way would be to create an array list.
ArrayList<InventoryItem> childInventory = new ArrayList<InventoryItem>();
Then create a setter that adds inventory items to this array
public void addChildItem(InventoryItem child)
childInventory.add(child);
This way you would have a list of all of the child items within the item. You could also make a method to return a list of all of the child items in either an array or an ArrayList.
public ArrayList<InventoryItem> getChildItems()
return childInventory;

About sorting array list

I am trying to ensure that the objects i insert in productDatabase have not been already inserted and that i sort my arraylist using method sortData but without using any comparators in method sortData
public class Application {
public static void main(String[] args) {
Product p = new Product(15,"test",3.45);
Product p2 = new Product(15,"test",3.45);
Product p3 = new Product(4716,"koukouroukou",1.25);
Product p4 = new Product(6002,"bananofatsoula",0.60);
ProductDatabase productDatabase = new ProductDatabase();
productDatabase.addProduct(p);
productDatabase.addProduct(p2);
productDatabase.addProduct(p3);
productDatabase.addProduct(p4);
productDatabase.printDatabase();
productDatabase.sortDatabase();
productDatabase.printDatabase();
}
public class Product {
private int code;
private String name;
private double price;
public Product(int code, String name, double price){
this.code = code;
this.name = name;
this.price = price;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String toString(){
return code+" , description: "+name+", price: "+price;
}
public int hashCode(){
return 31 * code + name.hashCode();
}
public boolean equals(Object o){
Product other = (Product)o;
if (this.code == other.code){
return true;
}
else{
return false;
}
}
import java.util.ArrayList;
import java.util.Collection;
public class ProductDatabase {
private ArrayList<Product> productDatabase;
public ProductDatabase(){
productDatabase = new ArrayList<Product>();
}
public void addProduct(Product p){
if(!productDatabase.contains(p)){
productDatabase.add(p);
}
}
public void printDatabase(){
for(Product product : productDatabase){
System.out.println(product);
}
}
public void sortDatabase(){
// ????????????????????????????????????????????????????????????
So my questions are
Does contain(p) is enough to ensure that the same product is not already in the list?
products are the same when they have the same code and name.if not what i have to do?
How i sort my withous using comparators in class ProductDatabase.maybe by a new method in product ?
Does productDatabase extends Product???
You can return bool value in order to know the product is already there or not . Code is used to ensure the differentiation of products if not add another code id.
Product instance will carry information of just one Product so Sort must be done in the member function of class having all the records of product, not just one.
No product_database does not extend product . It is a log of product class not a part .
your questions 1 and 2 are a little unclear. Can you re-write them? As for question 3. No ProductDatabase does not extend product, neither should it. ProductDatabase HAS products. ProductDatabase is not a product
Yes, contains() is enough (in our case) to ensure uniqueness
Since you implemented equals and hashCode - you're good
You don't need to sort if you don't have another purpose to do so, but since you're using an ArrayList every time contains() is called it iterates the whole list which is not very efficient. A better implementation would use Set (a HashSet for example)
ProductDatabase does not have to extend Product - it contains a list/set of products but it doesn't have any character/behavior like Product
Yes, contain(p) is enough to ensure that the same product is not already in the list, because you overrided "equals" method.
In "equals" you can use shorter construction:
Product other = (Product)o;
return this.code == other.code;
For sort ArrayList with java.util.Collections class two options possible:
Collections.sort(List list, Comparator c). You have to write own Comparator class and pass as second parameter.
Collections.sort(List list) and class Product must implement Comparable interface
Yes, Contain(p) is enough to ensure that the same product is not already in the list BUT that is NOT efficient. Use a Set instead of ArrayList.
For question 2, you have to decide the when the two products are equal and code that in your equals method like you did for 'product code'

Storing multiple object types in a List

I have following homework about computer store:
There are several class include: Monitor, Case, Mouse, Keyboard.
All the classes have common fields: id, name, price, quantity.
Each class has some unique fields.
All most features are: add, update, delete, find, show list, save, load file
-So, first I will create a class named Product have 4 common fields. Above classes will extends from Product.
-Then, I think I maybe create a ComputerStore class which have a field is items type ArrayList. items stores all objects which are instance of 4 above classes But I'm not sure.
Whether it is reasonable? I need some ideas
Before , I always use ArrayList store for only one class like
List <String> list = new ArrayList<String>();
Now they are multi type. I think it's generic in Java, right??
In case, I want to update for 1 items. I must think about how to change information for them. Ex: mouse for some code, keyboard for another code. Anyway, thank for everybody!
Your approach is 100% reasonable.
You are completely on the right track with "generics". First, check out the official enter link description here.
Next, just think about your data in real world terms, like you are already doing: Monitor, case, mouse, and keyboard are products. Your computer store's inventory is a list of products.
Hint: A list of products.
Put that together with what you learn about generics through that tutorial, and you'll be good to go.
You could use java generic.First create a java collection (ex: List) with supper class type, Product. Now you could add any sub classes (Monitor , Keyboard etc) in your collection (List) that extends of class Product.
public class Product{
}
public class Monitor extends Product{
}
public class Keyboard extends Product{
}
List<Product> products = new ArrayList<Product>();
products.add(new Monitor());
products.add(new Keyboard());
Since you have a superclass (Product), you can have the list's type as Product, i.e.
List<Product> list = new ArrayList<Product>();
list.add(new Mouse());
list.add(new Keyboard());
It will allow you to iterate them and list their name and price without caring for the class, but if you intend to take an item out of the list you'll need to check its actual type (depending on what you do with it).
You can do like below
import java.util.List;
import java.util.ArrayList;
class Test{
public static void main(String... args){
List<MultiObj> multiObjs = new ArrayList();
MultiObj ob = new MultiObj(); multiObjs.add(ob);
ResX xOb = new ResX(); multiObjs.add(xOb);
ResY yOb = new ResY(); multiObjs.add(yOb);
ResZ zOb = new ResZ(); multiObjs.add(zOb);
for (int i = 0; i < multiObjs.size(); i++ ) {
System.out.println(multiObjs.get(i).getV());
}
System.out.println("Waoo its working");
}
}
class MultiObj{
public String greet(){
return "Hello World";
}
public String getV(){
return "Hello World";
}
}
class ResX extends MultiObj{
String x = "ResX";
public String getX(){
return x;
}
public String getV(){
return x;
}
}
class ResY extends MultiObj{
String y = "ResY";
public String getY(){
return y;
}
public String getV(){
return y;
}
}
class ResZ extends MultiObj{
String z = "ResZ";
public String getZ(){
return z;
}
public String getV(){
return z;
}
}
You could do this:
public class Item {
public Item(int id, string name, float price, int amount, int ArrayID) {
if (ArrayID == 1) {
ID1 = id;
name1 = name;
price1 = price;
amount1 = amount;
}
if (ArrayID == 2) {
ID2 = id;
name2 = name;
price2 = price;
amount2 = amount;
}
if (ArrayID == 3) {
ID3 = id;
name3 = name;
price3 = price;
amount3 = amount;
}
if (ArrayID == 4) {
ID4 = id;
name4 = name;
price4 = price;
amount4 = amount;
}
}
//ArrayID #1
public static int ID1;
public static String name1;
public static float price1;
public static int amount1;
//ArrayID #2
public static int ID2;
public static String name2;
public static float price2;
public static int amount2;
//ArrayID #3
public static int ID3;
public static String name3;
public static float price3;
public static int amount3;
//ArrayID #4
public static int ID4;
public static String name4;
public static float price4;
public static int amount4;
public static int[] id = ID1, ID2 ID3, ID4;
//so forth...
}

Can I use my objects without fully populating them?

I have situation. I have to create a Sports Club system in JAVA. There should be a class your for keeping track of club name, president name and braches the club has. For each sports branch also there should be a class for keeping track of a list of players. Also each player should have a name, number, position and salary.
So, I come up with this. Three seperate classes:
public class Team
{
String clubName;
String preName;
Branch []branches;
}
public class Branch
{
Player[] players;
}
public class Player
{
String name;
String pos;
int salary;
int number;
}
The problems are creating Branch[] in another class and same for the Player[]. Is there any simplier thing to do this? For example, I want to add info for only the club name, president name and branches of the club, in this situation, won't i have to enter players,names,salaries etc. since they are nested in each other. I hope i could be clear. For further questions you can ask.
Here's a more complete, formal example of your scenario using conventional Accessors/Mutators (getters/setters), constructors, and Lists. The main() method below illustrates how to use your classes.
public class SportsClub
{
public static void main(String[] args)
{
//Create a team without any branches
Team myTeam = new Team("Southpaws", "South");
//Create a new Branch without any players
Branch myBranch = new Branch();
//Add myBranch to myTeam
myTeam.getBranches().add(myBranch);
//Create a new player
Player myPlayer = new Player("Bob", "Center", 120, 3);
//Add myPlayer to myBranch (and therefore myTeam)
myBranch.getPlayers().add(player);
}
}
public class Team
{
private String clubName;
private String preName;
private List<Branch> branches;
public Team(String clubName, String preName)
{
this.clubName = clubName;
this.preName = preName;
branches = new ArrayList<Branch>();
}
public String getClubName() { return clubName; }
public String getPreName() { return preName; }
public List<Branch> getBranches() { return branches; }
public void setClubName(String clubName) { this.clubName = clubName; }
public void setPreName(String preName) { this.preName = preName; }
public void setBranches(List<Branch> branches) { this.branches = branches; }
}
public class Branch
{
private List<Player> players = new ArrayList<Player>();
public Branch() {}
public List<Player> getPlayers() { return players; }
public void setPlayers(List<Player> players) { this.players = players; }
}
public class Player
{
private String name;
private String pos;
private Integer salary;
private Integer number;
public Player(String name, String pos, Integer salary, Integer number)
{
this.name = name;
this.pos = pos;
this.salary = salary;
this.number = number;
}
public String getName() { return name; }
public String getPos() { return pos; }
public Integer getSalary() { return salary; }
public Integer getNumber() { return number; }
public void setName(String name) { this.name = name; }
public void setPos(String pos) { this.pos = pos; }
public void setSalary(Integer salary) { this.salary = salary; }
public void setNumber(Integer number) { this.number = number; }
}
To answer your question, yes, you can create these objects without populating the Lists with players. The SportsClub.main() above illustrates that.
I would use a List rather than an array since they're (easily) dynamically resizable, but otherwise, you're on the right track.
Think about encapsulation and visibility too. Make all those fields private and provide accessors.
You could create an empty Branch[] array (or better yet - a list) at initialization and add to it later, that way you don't have to enter all the information upon creation - same goes for Player[].
Something like:
public class Team
{
String clubName;
String preName;
private List<Branch> branches;
public Team (String club, String pre) {
clubName = club;
preName = pre;
branches = new LinkedList<Branch>();
}
public void addBranch (Branch branch) {..}
}
public class Branch
{
private List<Player> players;
public Branch () {
players = new LinkedList<Player>();
}
public void addPlayer (Player player) {..}
}
public class Player
{
String name;
String pos;
int salary;
int number;
}
I think that's good. You should probably have methods in the classes to manage your information though--don't try to do anything serious from "Outside" these classes.
to be more specific: All your members should be private and only used/accessed from within the classes--also in general avoid setters and getters, instead ask the class to do things for you.
For example, if you wanted to know how many players were in a branch, you would call branch.countPlayers, not access the Player array to count the players from outside.
If you wanted to know how many players were in a team, you would call team.countPlayers which would call branch.countPlayers for each Branch, sum them up and return the value.
If you wanted to see which branch a player was in, you would call Team.findPlayer(playerName). Team would call branch.hasPlayer(playerName) on each branch until it returned a true, then Team would return the Branch object that returned true.
etc.
Note that this resolves your "Populated or not" issue. If you simply have methods like "hasBranch()", "addBranch()", "removeBranch()" then it doesn't matter how or when you populate the branches array since you control it all within the Team class you can change it's implementation at any time and not change a single line outside that class.
You won't have to enter anything into the players array, nor the branch[]. Provided you make the fields accessible, of have properties, you will be able to put them in however you like.
The class structure looks good to me, but a List would be better so that you don't have to worry about resizing arrays down the road.
Nothing wrong with your classes. I personally would use a strongly-typed List to store the branches and players:
public class Team
{
String clubName;
String preName;
List<Branch> branches;
}
public class Branch
{
List<Player> players;
}
Not sure of the requirement, but you'd probably want to have some kind of identifier or name for each Branch, right?
There's nothing in these classes that forces you to create new players just to instantiate a Branch. The list of Players can remain null or empty until you need them.

Categories

Resources