-3

Let's suppose I've the following Class Product:

public class Product {
    // Variables.
    private String name;      // Name  
    private Double price;     // Price

    Product() {}    // Default constructor with no parameters.

    Product(String name, Double price) {    // Constructor with parameters.
        this.name = name;
        this.price = price;
    }

    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() {    // Overriding "toString()".
        return "\nName: " + this.name + "\nPrice: " + this.price;
    }


public boolean equals(Object obj) {    // Overriding equals()
   if(this == obj) {
      return true;
   }
   if(obj == null || obj.getClass() != this.getClass()) {
      return false;
   }
   Product product = (Product) obj;
   return this.name.equals(product.name)&& this.price.equals(product.price);
}
    }

Now, let's suppose I've an ArrayList in my Main.class and my Main looks something like this:

import java.util.*;
    import java.io.*;
    public class Main {
        private static BufferedReader r = new BufferedReader (new InputStreamReader(System.in));
        private static String readln() throws IOException{
            return r.readLine();
        }
        private static long readInput() throws IOException{    // Use this to read input for the menu options.
            return Integer.valueOf(readln());
        }
        public static void menu(){    // Menu
            System.out.println("-------------------------" +
                    "\nAdd new product(1)" +
                    "\nSearch for product(2)" +
                    "\nDelete product(3)" +
                    "\nShow all products(4)" +
                    "\nReturn the number of products(5)" +
                    "\nExit(-1)" +
                    "\n-------------------------");
        }

        public static void main (String args[]) throws IOException{
            // This is the ArrayList for the "Product".
            ArrayList<Product> products = new ArrayList<Product>();
            int option = 0;
            do {
                menu();
                option = (int)readInput();
                switch (option){
                    case 1:{
                        System.out.println("Insert product name: ");
                        String name= readln();
                        System.out.println("Insert product price: ");
                        Double price = Double.parseDouble(readln());
                        products.add(new Product(name, price));
                        break;
                    }
                    case 2:{
                        System.out.println("Insert product name: ");
                        String name= readln();
                        System.out.println("Insert product price: ");
                        Double price= Double.parseDouble(readln());
                        if ((products.contains(new Product (name, price)))){
                            System.out.println("Works!");
                        }

                        break;
                    }
                    case 3:{

                        break;
                    }
                    case 4:{

                        break;
                    }
                    case 5:{
                        System.out.println("Number of products: " + products.size());
    //This prints with no problems, therefor the objects DO exist in the ArrayList.
                        break;
                    }
                }
            }while((option > 0) && (option < 6));
        }
    }

According to this in order to insert an object into an ArrayList you need to write it like this "ArrayListName.add(new ObjectName(param1, param2));" or you can create an object called object1 and then add it with ArrayListName.add(object1); In my case, from what I understand, I'm inserting objects into the ArrayList but those objects do not really exist, because if I tried to use the overridden toString() method, it does not print anything. If my understanding is wrong, why does it not print anything? According to this, my method is correct.

If I've understood this correctly, objects do not need a variable to point to them, but if you've directly inserted them into an ArrayList, like I have, how are you supposed to get the index position of an object? Because the equals() in my case, compares objects, so you can't use it to search the ArrayList. Nor can you try something like "products.contains(name, price);" because, .contains() uses equals().

I was also thinking of doing something like this, but it's only useful if you want to create a new Class and not an object like product1, in my case. I gave up on it as well because forName() kept saying that it can't find the Class for some reason that I could not find out why.

What about the "Delete" option? Would it work the same way as the "Search" one?

Edit: for the equals() the last line, you can also put:

if( (this.price.equals(product.getPrice())) && (this.name.equals(product.getName())) ) {
            return true;
        }
Doombringer
  • 596
  • 4
  • 19
  • 2
    How about you ask one question at a time? Where do you call `toString()`? – Murat Karagöz Dec 01 '17 at 09:25
  • This is an example of printing the first element of your arraylist: `System.out.println(products.get(0))`. It will invoke your custom `toString()` method. I guess you want to loop on each product and print them when user selects the 4th menu option. – Oneiros Dec 01 '17 at 09:26
  • you will need to overwrite the https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode-- aswell in order to compare the objects, check this answer too: https://stackoverflow.com/questions/16069106/how-to-compare-two-java-objects – Edwin Dec 01 '17 at 09:28
  • @MuratK. I do not. ".....because if I tried to use the overridden toString() method...." – Doombringer Dec 01 '17 at 09:32
  • @Oneiros When I try to print stuff from the `ArrayList`, it works, but the problem is, how would you search it for an object when you do not have a variable that points to it, supposing you don't know the index of that object either? – Doombringer Dec 01 '17 at 09:34
  • You said "if I tried to use the overridden toString() method, it does not print anything", now you say it works... the search is a different problem – Oneiros Dec 01 '17 at 09:37
  • @Oneiros Oh, my bad, I misunderstood your first post and I guess I didn't know that `get(0)` actually uses `toString()`, but then again, how would you do the searching thing? – Doombringer Dec 01 '17 at 09:45
  • `get(0)` does not use `toString()`. With `get(0)` you retrieve the product at index `0` (the first one) from the arraylist, as a `Product`. Then `System.out.println()` try to convert it to a string, by using the `toString()` method. About the searching problem: do you want to let the user input any string and retrieve all products that match that string? – Oneiros Dec 01 '17 at 10:05
  • Yes, but the problem is, the `ArrayList` contains objects, not strings, so I couldn't figure it out. – Doombringer Dec 01 '17 at 10:07
  • 1. Create a new list 2. Loop on each product 3. Check if the product matches 4. If it does, add it to the new list 5. Return the list. How do you check if the product matches? It's up to you... do you want to search by name? By price? By both? – Oneiros Dec 01 '17 at 10:09
  • We should not compere Double (class) values with `==` we should use instead euqals on that. I have fixed my answer. – Damian0o Dec 01 '17 at 11:10

2 Answers2

1

To make it work you should also rewrite your equals method to compere fields inside people object overriding equals method

There could be a bug in your parametrized constructor. It should looks like:

Product(final String name, final Double price) {    // Constructor with parameters.
    this.name = name;
    this.price = price;
}

Final word prevent us to change value of incoming parameter.

According to the article above the implementation should be

@Override
public boolean equals(Object obj) {    // Overriding "equals()".
    // at first check if objects are the same -> your code
    if (this == obj) {
        return true;
    }

    // secondly we chack if objects are instances of the same class if not return false
    if (obj != null && this.getClass() != obj.getClass()) {
        return false;
    }

    // then compare objects fields. If fields have the same values we can say that objects are equal.
    Product product = (Product) obj;
    return this.name.equals(product.name) && this.price.equals(product.price);
}

To handle nulls in fields we can write additional checks.

With new implementation of equals method to search for the element on the list you can pass new instance of product to contains mathod

instead of doing

products.contains(name, price);

try

products.contains(new Product(name, price))

To delete element from the list you can first find index of element and the use remove method.

products.remove(products.indexOf(new Product(name, price)))
Damian0o
  • 653
  • 5
  • 15
  • I tried changing the `equals()` to `public boolean equals(String name, Double price) { if ((this.name == name) && (this.price == price)) { return true; } return false; }` and `public boolean equals(Product obj) { if (this==obj) { return true; } return false; }` but it did not work. As in, when I tried putting in the main `if (products.contains(new Product(name, price))){ System.out.println("Works"); }`, it did not print anything. – Doombringer Dec 01 '17 at 09:56
  • I have edited my answer to give you euqals method example. – Damian0o Dec 01 '17 at 10:14
  • I put `return this.name == product.name && this.price == product.price;` because other wise, it says that it cannot resolve symbol "name" and "price", but I still get nothing. This is weird. I do appreciate you taking the time to help me out though, a lot. – Doombringer Dec 01 '17 at 10:24
  • your equals method signature should look like `public boolean equals(Object obj)` – Damian0o Dec 01 '17 at 10:33
  • It does. The method has no errors in it, but this `if (products.contains(new Product(name, price))){ System.out.println("Works"); }` sill doesn't print "Works", is the `if` wrong? – Doombringer Dec 01 '17 at 10:35
  • Can you edit your question amd fix code you delivered? Because it does not compile. – Damian0o Dec 01 '17 at 10:43
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/160278/discussion-between-damian0o-and-doombringerbg). – Damian0o Dec 01 '17 at 10:50
  • I see additional bug in you code in parametrized constructor. – Damian0o Dec 01 '17 at 10:51
  • Oh my god. This `return this.name.equals(product.name) && this.price.equals(product.price);` made it work. Thank you so much for helping me out mate. Really appreciate it. <3 – Doombringer Dec 01 '17 at 11:15
1

Actually, this is not good example to understand of working with ArrayList. First of all, this collection is not good for product list. Yes, you could use it, but Map is much better. I do not think, that you're learning Java. If so, I prefer to use Map instead of List.

Moreover, I recommend to avoid using option numbers. Use named constants as minimum, but using OOP is much better. E.g. you could use enum where each element is one menu option.

E.g. like below.

public class Main {
    public static void main(String... args) {
        List<Product> products = readProducts();
        // final list of products
    }

    private static List<Product> readProducts() {
        Map<String, Product> products = new LinkedHashMap<>();

        try (Scanner scan = new Scanner(System.in)) {
            while (true) {
                MenuItem.show();
                MenuItem menuItem = MenuItem.parseOption(scan.nextInt());

                if (menuItem == MenuItem.EXIT)
                    break;

                menuItem.action(products, scan);
            }
        }

        return products.isEmpty() ? Collections.emptyList() : new ArrayList<>(products.values());
    }

    private enum MenuItem {
        ADD_NEW_PRODUCT(1, "Add new product") {
            @Override
            public void action(Map<String, Product> products, Scanner scan) {
                System.out.println("Insert product name: ");
                String name = scan.next();

                System.out.println("Insert product price: ");
                double price = scan.nextDouble();

                if (products.containsKey(name))
                    products.get(name).setPrice(price);
                else
                    products.put(name, new Product(name, price));
            }
        },
        SEARCH_FOR_PRODUCT(2, "Search for product"),
        DELETE_PRODUCT(3, "Delete product") {
            @Override
            public void action(Map<String, Product> products, Scanner scan) {
                System.out.println("Insert product name: ");
                String name = scan.next();

                products.remove(name);
            }
        },
        SHOW_ALL_PRODUCTS(4, "Show all products"),
        RETURN_THE_NUMBER_OF_PRODUCTS(5, "Return the number of products") {
            @Override
            public void action(Map<String, Product> products, Scanner scan) {
                System.out.println("Number of products: " + products.size());
            }
        },
        EXIT(-1, "Exit");

        private final int option;
        private final String title;

        MenuItem(int option, String title) {
            this.option = option;
            this.title = title;
        }

        public void action(Map<String, Product> products, Scanner scan) {
        }

        public static MenuItem parseOption(int option) {
            for (MenuItem menuItem : values())
                if (menuItem.option == option)
                    return menuItem;
            return EXIT;
        }

        public static void show() {
            System.out.println("-------------------------");

            for (MenuItem menuItem : values())
                System.out.printf("%s(%d)\n", menuItem.title, menuItem.option);

            System.out.println("-------------------------");
        }
    }
}
Oleg Cherednik
  • 17,377
  • 4
  • 21
  • 35