-2

So, i am making an eshop in java, but I am facing a problem that I can't solve. The eshop sells 4 items, so we have the class Item and the subclasses Pen, Pencil, Notebook and Paper and I have stored them all in an arraylist. I want to make a method, which prints the products in categories according the type of the object that they are. For example: Pen -> pen1, pen2 Pencil-> pencil1,pencil2

The problem that I have is that I don't know how to recognise in the arraylist that for example pen1 is a pen object and print it at the pen category. I tried to use an iterator, but i am not very familiar with it, so i couldn't do much.

John Baker
  • 29
  • 3

2 Answers2

4

Obligatory Java Streams solution:

Map<Class<? extends Item>, List<Item>> map = yourList.stream()
    .collect(Collectors.groupingBy(Object::getClass));

This groups the list by class, resulting in a map with each class as a key and a list of objects of that class as value.

In order to get all pencils:

List<? extends Item> pencils = map.get(Pencil.class);

getClass()

Retrieves the class of the instance.

Pencil myItem = new Pencil();
myItem.getClass(); // Returns Class[com.example.yourpackage.Pencil]

instanceof

myItem instanceof Item checks if the variable myItem is an instance of the Item class, that means either an Item, or one of its subclasses, for example Pencil. The comparison, of course, returns a boolean.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
MC Emperor
  • 22,334
  • 15
  • 80
  • 130
1

Probably you already have something like this:

interface Item {...}
class Pen implements Item {...}
class Pencil implements Item {...}
class Notebook implements Item {...}
class Paper implements Item {...}

And somewhere in the application there is an ArrayList:

 List<Item> items = new ArrayList<>();
 items.add(new Pen("pen1"));
 items.add(new Pencil("pencil1"));
 items.add(new Pen("pen2")); 
 items.add(new Paper("paper1"));    

So in order to print only, say Pen-s you can use the following code:

private void printWithForEachLoop(List<Item> list, Class<? extends Item> cl) {
   for(Item item : list) {
        if(cl.isAssignableFrom(item.getClass())) {
            System.out.println(item);
        }
    }
}

If you can use streams (java 8+), you can have the following implementation:

 private void printWithStreams(List<Item> list, Class<? extends Item> cl) {
       list.stream().filter( o -> 
         cl.isAssignableFrom(o.getClass())).forEach(System.out::println);
 }

Another way is using the instanceof operator, but it requires you to 'hardcode' the class name, for example in case of streams you can do:

items.stream().filter( o -> o instanceof Pen).forEach(System.out::println);
Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97