3

I am trying to get the records with min distance, min speed and max speed in the result of my query. Currently I am getting the shortest distance but I am facing problem to get the min and max speed and I am asking myself whether it is possible to add another public int compareTo(BehaviourItem otherItem) method in the BehaviourItem class to reach that but I am getting the error Duplicate method compareTo(BehaviourItem) in type BehaviourItem.

How can I get the min and max speed from the BehaviourItem class?

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); } } 
1
  • 1
    you could create custom Comparators and pass them to Collection.sort method Commented Jun 22, 2015 at 11:54

4 Answers 4

7

You should not let BehaviourItem implement Comparable as it doesn’t have a natural order. Instead, implement different Comparators for the different properties.

Note that in Java 8, you can implement such a Comparator simply as

Comparator<BehaviourItem> orderBySpeed=Comparator.comparingInt(BehaviourItem::getSpeed); 

which is the equivalent of

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 the other property.

Almost every collection method using an order has an overload supporting to pass a Comparator to define the order instead of using the natural order:

Collections.sort(behavList, orderBySpeed); 

resp.

Collections.sort(behavList, orderByDistance); 

You can even create the comparator ad-hoc:

Collections.sort(behavList, Comparator.comparingInt(BehaviourItem::getDistance)); 

and

Collections.sort(behavList, Comparator.comparingInt(BehaviourItem::getSpeed)); 

but the stream API allows you to look for minimum or maximum even without sorting:

Optional<BehaviourItem> minBySpeed=behavList.stream() .max(Comparator.comparingInt(BehaviourItem::getSpeed)); 
Sign up to request clarification or add additional context in comments.

2 Comments

how can I return the both item here in this method compare(BehaviourItem otherItem1, BehaviourItem otherItem2)? and where can I put that Comparator<BehaviourItem> orderBySpeed=Comparator.comparingInt(BehaviourItem::getSpeed);?
You can place the variable where you want, you can make it a static variable of BehaviourItem if you think that it will be used often, but you can also place it right before the use and, as said, you can even create the comparator ad-hoc, passing it to the sort (or max) method without the need for the variable at all.
1

Comparable basically defines an object that has a natural order (e.g. numbers) and thus there can be only one compareTo() method.

For getting min/max for one value you can use a sorted collection, e.g. a list, and access the first and last elements.

However, since your BehaviourItem doesn't have a natural order (would it be according to speed or distance?), you'd have to define the order based on the situation. That's where a Comparator comes into play: when you want to sort by speed you use a comparator that compares speed, if you want to sort by distance you use a comparator for the distance etc.

Of course if speed and distance change a lot and you always need to get min/max for both you can also just iterate over all items and select min/max the classic way.

Another option, since you're using a query anyways, might be to directly add min(speed), max(speed) etc. This would either require a separate query or be added to each result row which in turn might reduce query speed but if you only get a few rows it might still be worth it.

Comments

1

You cannot define another compareTo() function in your BehaviourItem class , but you can create custom comparators and use that 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 as -

Collections.sort(behavList, BehaviourItem.BehaviourItemComparator) 

Comments

0

Use Comparator instead of Comparable.

You can define as many number of ordering behavior as you want.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.