Get min and max value of multiple elements using Comparable
I am trying to get records from min distance, min speed and max speed
as a result of my query. I am currently getting the shortest distance, but I am facing a problem to get the min and max speed and I am asking myself if it is possible to add another method public int compareTo(BehaviourItem otherItem)
to the class BehaviourItem
to achieve this, but I am getting an error Duplicate method compareTo(BehaviourItem) in type BehaviourItem
.
How can I get the minimum and maximum speed from the class BehaviourItem
?
Code:
PreparedStatement prepared = con
.prepareStatement("SELECT speed, stop_distance from behaviour where mac = ? and stop_name = ?");
prepared.setString(1, macD);
prepared.setString(1, sto_nam);
ResultSet rsBehav = prepared.executeQuery();
List<BehaviourItem> behavList = new ArrayList<BehaviourItem>();
while (rsBehav.next()) {
int distance = rsBehav.getInt("stop_distance");
int speed = rsBehav.getInt("speed");
BehaviourItem behItem = new BehaviourItem(distance, speed);
behavList.add(behItem);
}
Collections.sort(behavList);
int minDistance = behavList.get(0).getDistance();
BehaviourItem class:
public class BehaviourItem implements Comparable<BehaviourItem>{
int speed;
int distance;
public BehaviourItem(int speed, int distance) {
super();
this.speed = speed;
this.distance = distance;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getDistance() {
return distance;
}
public void setDistance(int distance) {
this.distance = distance;
}
@Override
public int compareTo(BehaviourItem otherItem) {
// TODO Auto-generated method stub
return Integer.compare(this.distance, otherItem.distance);
}
}
source to share
Cannot be used BehaviourItem
Comparable
as it has no natural order. Instead, implement different Comparator
s for different properties.
Note that in Java 8 you can implement something as Comparator
simple as
Comparator<BehaviourItem> orderBySpeed=Comparator.comparingInt(BehaviourItem::getSpeed);
which is equivalent
Comparator<BehaviourItem> orderBySpeed=new Comparator<BehaviourItem>() {
public int compare(BehaviourItem a, BehaviourItem b) {
return Integer.compare(a.getSpeed(), b.getSpeed());
}
};
or
Comparator<BehaviourItem> orderByDistance
=Comparator.comparingInt(BehaviourItem::getDistance);
for another property.
Almost every collection method using order has overloading support to pass Comparator
in order to define the order rather than using natural ordering:
Collections.sort(behavList, orderBySpeed);
respectively.
Collections.sort(behavList, orderByDistance);
You can even create an ad-hoc comparator:
Collections.sort(behavList, Comparator.comparingInt(BehaviourItem::getDistance));
and
Collections.sort(behavList, Comparator.comparingInt(BehaviourItem::getSpeed));
but the stream API allows you to search for the minimum or maximum value even without sorting:
Optional<BehaviourItem> minBySpeed=behavList.stream()
.max(Comparator.comparingInt(BehaviourItem::getSpeed));
source to share
Comparable
basically defines an object that has natural ordering (like numbers) and therefore there can only be one method compareTo()
.
To get the min / max for a single value, you can use a sorted collection for example. list and access to the first and last items.
However, since your BehaviorItem does not have a natural ordering (would it be in speed or distance?), You will need to define an order based on the situation. What comes into play Comparator
: when you want to sort by speed, you use a comparator that compares the speed, if you want to sort by distance, you use a comparator for distance, etc.
Of course, if the speed and distance change a lot and you always need to get the min / max for both, you can also just iterate over all the items and choose the min / max the classic way.
Another option, since you are using query anyway, might be to add directly min(speed), max(speed)
, etc. This will either require a separate query or be added to each row of results, which in turn can slow down the query speed, but if you only get a few rows that might still be worth it.
source to share
You cannot define another function compareTo()
in your class BehaviourItem
, but you can create your own comparators and use them to sort the list.
An example of a custom comparator -
public class BehaviourItem implements Comparable<BehaviourItem>{
.
.
.
@Override
public int compareTo(BehaviourItem otherItem) {
// TODO Auto-generated method stub
return Integer.compare(this.distance, otherItem.distance);
}
static class BehaviourItemComparator implements Comparator<BehaviourItem>
{
public int compare(BehaviourItem b1, BehaviourItem b2)
{
return Integer.compare(b1.getSpeed(), b2.getSpeed());
}
}
}
Then you can use it like -
Collections.sort(behavList, BehaviourItem.BehaviourItemComparator)
source to share