Dummy
Dummy

Reputation: 29

Java static method ArrayList

I have 2 clases named Fruits and Balls. For each of them, one of the attribute is Price. I need to make a static metod that return from an mix aray only the element with the smallest Price. I have the objects f1, f2, f3, b1, b2, b3.

I've made an ArrayList list like this:

{ Fruit f1 = new Fruit("Apple", "Red", "Summer", 9.5);
  ...
  Ball b1 = new Ball("Red", "Stripes", 10.5);
  ...
  ArrayList list = new ArrayList();
  list.add(f1);
  list.add(b1);
  ...
}

Now regarding the method I have to make I started like this:

static void method(ArrayList list) {
for (int i = 0; i < lista.size(); i++) {
}

I get stucked in the mix of getting elemets out of the array and the getters used to find the price for each element. Can you help me?

Even if you don t understand what I m trying to do could you help me with some tips of mix arays of different elements. Thank you!

Upvotes: 0

Views: 3762

Answers (3)

Christian Roth
Christian Roth

Reputation: 9

If fruits and balls have a price, you should make both abstract classes and let them implement the Price interface.

For example

public abstract class Fruit implements Price

public abstract class Balls implements Price

with

public interface Price {
    double getPrice();
}

Then, you could have an Apple with the price 9.5

public class Apple extends Fruit {

    @Override
    public double getPrice() {
        return 9.5;
    }

}

and a RedBall with the price 10.5

public class RedBall extends Ball {

    @Override
    public double getPrice() {
        return 10.5;
    }

}

At the end, you are able to define a List of Price elements (item with a price) like this:

    Apple apple = new Apple();
    RedBall redBall = new RedBall();

    ArrayList<Price> items = new ArrayList<Price>();
    items.addAll(apple, redBall); 

This way, there's no need to mix different elements.

Upvotes: 1

nits.kk
nits.kk

Reputation: 5316

There are few points which you should consider.

  1. Having a collection which has mixed type is a BAD practice as the list you have in your case can later be (by mistake of yours or some other Co developer) modified to add an object of Employee class, Student class or any other class. although you expected the list to have only object of Fruit and Ball.

So following this guideline let's have a ArrayList containing objects of a specific type. Let's call this type as Item (simplest name, you can choose more contextual name) Better make it an Interface. Also as we need to access price so let's have a function(method as we call in Java) named getPrice(). The implementing classes Ball and Fruit will implement this method and return price attribute.

But we need to have Ball and Fruit in the list so let's implement interface Item by both of these classes.

Our ArrayList will be now be like

ArrayList < Item > list  = new ArrayList<>();

This ArrayList is capable of adding object of Ball and Fruit as both of these classes implement the interface Item

  1. Instead of adding the reference of array (as in your question) you need to add elements of the array in the list. Simple approach : In a for loop iterate the array of Fruit and add each fruit in ArrayList. Similarly add elements of array of Ball in the same ArrayList.

Now iterate the ArrayList of type Item and access the getPrice() and hopefully your job will be done.

Upvotes: 1

A. Bandtock
A. Bandtock

Reputation: 1241

So the problem you've come across is that you're not typing your list, creating a new ArrayList() without specifying a type is functionally the same as creating a new ArrayList<Object>(). When you then call the items from within this list, you will have an Object returned, which doesn't have the price attribute

With an implementation of streams you find a fairly simple solution to this problem:

double minFruitPrice = Stream.of(f1, f2, f3)
                          .reduce((acc, val) -> acc.price < val.price ? acc : val)
                          .orElseThrow(() -> new RuntimeException("No fruits provided!")) // reduce with 1 argument returns an optional
                          .getPrice(); // Always use a getter

The "correct" implementation in this case though, is to create an object with a price attribute:

abstract class PricedObject {
  private double price;

  public double getPrice() {
    return price;
  }

  public void setPrice(double price) {
    this.price = price;
  }
}    

Then create your Fruit and Ball objects which will extend that class (taking on its attributes)

class Fruit extends PricedObject {
    private String type;
    private String colour;
    private String season;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getColour() {
        return colour;
    }

    public void setColour(String colour) {
        this.colour = colour;
    }

    public String getSeason() {
        return season;
    }

    public void setSeason(String season) {
        this.season = season;
    }
}

And

class Ball extends PricedObject {
    private String colour;
    private String pattern;

    public String getColour() {
        return colour;
    }

    public void setColour(String colour) {
        this.colour = colour;
    }

    public String getPattern() {
        return pattern;
    }

    public void setPattern(String pattern) {
        this.pattern = pattern;
    }
}

Then use those objects inside the streams implementation given above:

Stream.of(f1, f2, f3, b1, b2, b3)
    .reduce((acc, val) -> acc.getPrice() < val.getPrice() ? acc : val);

Which will return an Optional of the PricedItem with the lowest price. You can then call .get() to get the value from the optional, although it's safer to use one of the orElse options.

Upvotes: 1

Related Questions