How to best calculate the sum of a objects' property? - java

If an object car has a property fuel, and I have a list of these objects cars: how can I best calculate the sum of this property getCarsFuel() of all objects in the list?
class CarStock {
List<Car> cars;
public int getCarsFuel() {
int result = 0;
for (Car car : cars) {
result += car.getFuel();
}
return result;
}
}
class Car {
int fuel;
}
Are there better ways, or can't it be done less "boilerplate".
I could image something like sum(List<T> list, String property) -> sum(cars, "fuel")
?

If you can use lambdaj, you can write something like:
import static ch.lambdaj.Lambda.*;
List<Car> cars = ...;
int result = sumFrom(cars).getFuel();
For some more examples of how to use lambdaj, see the Features page on the lambdaj wiki.

Related

Sorting objects in an arraylist by price attributes

Im working on this really small project, I've got an arraylist of car objects and im trying to print all the cars out in price ascending order. When i look around online every seems to be doing it with an array rather than are arraylist?
Any ideas on how i can make this possible with an array list? Below is the code i have.
public ArrayList<Car> sortPriceAcending(ArrayList<Car> cars) {
ArrayList<Car> sortedCars = new ArrayList<Car>();
Car temp;
for (int j = 0; j < cars.size() - 1; j++) {
for (int i = 0; i < cars.size() - 1; i++) {
Car car = (Car) cars.get(i);
Car car1 = (Car) cars.get(i + 1);
if (car.getPrice() > car1.getPrice()) {
temp = car;
cars.get(i) = cars.get(i + 1);
cars.get(i + 1) = temp;
sortedCars = cars;
}
}
}
return sortedCars;
}
There are many sorting algorithms available. Java itself already offers a good one and you can just use it with Collections#sort (official documentation). The method accepts any kind of List and ArrayList is one of them.
Therefore you need to define on which order you want to sort, you want to sort by prices.
You can define a natural ordering on your cars by implementing Comparable like this:
public class Car implements Comparable<Car> {
#Override
public int compareTo(Car other) {
return Integer.compare(this.getPrice(), other.getPrice());
}
// The other stuff of the car class
}
After that you can just use Collections.sort(cars) and it will sort based on this natural ordering you have defined.
However for general cars it might not be the best idea that their natural ordering is on prices. Therefore you can always define a Comparator object and use this for the ordering:
public class CarPriceComparator extends Comparator<Car> {
#Override
public int compareTo(Car first, Car second) {
return Integer.compare(first.getPrice(), second.getPrice());
}
}
And you can use it with Collections.sort(cars, new CarPriceComparator()).
If you like Lambda expressions and method references which came with Java 8 you can also define the equivalent Comparator with less code like seen here:
Collections.sort(cars, Comparator.comparingInt(Car::getPrice))
Hey Have you tried using comparator interface?
If you just have to sort always with price only try using comparable interface.
You can refer the following link for details :
Let me know if you need more details
https://www.javatpoint.com/difference-between-comparable-and-comparator

java sort list of objects by specifiable attribute

I want to sort a List of objects by a specified attribute of those objects and I want to choose which attribute should be used for sorting. Example:
class Car{
private String name;
private String colour;
public enum sortBy {NAME, COLOUR};
public String name(){
return name;
}
public String colour(){
return colour;
}
public static Car[] getSortedArray(Car[] carArray, sortBy sortType){
HashMap<Object, Car> carMap = new HashMap<Object, Car>();
Object[] sortArray = new Object[carArray.length];
Object value = null;
for(int i = 0; i < carArray.length; i++){
if(sortType == sortBy.NAME){
value = carArray[i].name();
}else if(sortType == sortBy.COLOUR){
value = carArray[i].colour();
}
carMap.put(value, carArray[i]);
sortArray[i] = value;
}
Arrays.sort(sortArray);
Car[] sortedArray = new Car[sortArray.length];
for(int i = 0; i < sortArray.length; i++){
sortedArray[i] = carMap.get(sortArray[i]);
}
return sortedArray;
}
}
//external:
Car[] cars = getSomeCars();
Car[] nameSortedCars = Car.getSortedArray(cars, Car.sortBy.NAME);
Car[] colourSortedCars = Car.getSortedArray(cars, Car.sortBy.COLOUR);
The idea is simple:
I put all values that i want to sort by into an array, and i create a map that maps these values back to their objects. After I sorted this array I take the objects mapped to these values and put them in the same order into a new array which is then sorted by these values. The values are just created with type Object so I can sort by multiple types (not just Strings as in the example).
This works fine unless you have two objects with the same attribute value, then only one object will be in the returned array, but two times.
Is there a better way to achieve this sorting?
It would be much simpler to use custom comparators:
To sort by name:
Arrays.sort(carArray, Comparator.comparing(Car::name));
To sort by colour:
Arrays.sort(carArray, Comparator.comparing(Car::colour));
So you could modify getSortedArray():
public static Car[] getSortedArray(Car[] carArray, Comparator<Car> comparator) {
Car[] sorted = carArray.clone()
Arrays.sort(sorted, comparator);
return sorted;
}
And call it like this:
Car[] sorted = getSortedArray(carArray, Comparator.comparing(Car::name));
Edit:
If you use a language version that does not support these features, you can create the comparators by explicitly creating a nested class that implements the Comparator interface.
This, for example, is a singleton Comparator that compares Car instances by name:
static enum ByName implements Comparator<Car> {
INSTANCE;
#Override
public int compare(Car c1, Car c2) {
return c1.name().compareTo(c2.name());
}
}
Then call:
Car[] sorted = getSortedArray(carArray, ByName.INSTANCE);
TL;DR: There's already a wheel for that.
I would say the easiest way to do this is to create a comparator:
final Comparator<Car> byName = Comparator.comparing(Car::name);
final Comparator<Car> byColour = Comparator.comparing(Car::colour);
Then just use the appropriate method on Arrays to sort by a comparator:
Arrays.sort(carArray, byName);
Now you want to do it with an enum? Just have the enum implements Comparator<Car>:
enum SortBy implements Comparator<Car> {
NAME(Comparator.comparing(Car::name)),
COLOUR(Comparator.comparing(Car::colour));
private final Comparator<Car> delegate;
private SortBy(Comparator<Car> delegate) {
this.delegate = delegate;
}
#Override
public int compare(final Car o1, final Car o2) {
return delegate.compare(o1, o2);
}
}
Want to sort by name then by colour? Easy:
final Comparator<Car> byName = SortBy.NAME.thenComparing(SortBy.COLOUR);
Want to sort by name in reverse order? Easy:
final Comparator<Car> byName = SortBy.NAME.reversed();
You're reinventing the wheel! Life will be much easier for you if you use the templated Collections API. To do this, you would work with List instead of arrays, define a Comparator to do your sorting, and then let the API do the work for you.
Comparator<Car> carComparator = new Comparator<Car>(){
public int sort(Car car1, Car car2){
//Sorting logic goes here.
}
}
List<Car> cars = getCars();
cars = Collections.sort(cars, carComparator); //the cars collection is now sorted.
If you wanted to sometimes sort by one attribute or another, you could make my variable carComparator into its own class and define which attributes to sort by in the constructor.
Hope that helps :)
Edit: As others have pointed out, this approach also works with arrays. But unless you have a good reason to be working with Arrays, working with Collections will generally be easier.
I think the solution would be more efficient if you passed a Comparator implementation to the Arrays.sort. Right now, you are looping n*2 from the looks of it, the hash map (O(1)) plus the Arrays.sort (which is another 0(n log n) or such). If you do the below, you could skip the 2 loops, and the map, you are using currently.
You can simply create a Comparator like (rough code):
class CarComparator implements Comparator<Car> {
enum compareType; //plus setter
public int compareTo(Car a, Car b) {
if(compareType == COLOUR) return a.colour.compareTo(b.colour);
if(compareType == NAME.....
}
}
, and then simply send the array of Cars to
Arrays.sort(cars, new CarComparator(COLOUR))
, or use more specialised comparator classes, one for each attribute, and a factory to render them, and of course don't create a new Comparator() for each sort if this is happening often. :-)
Overall, this approach should make your code more efficient.
}

Ordering array by a property in Java

I have an array of objects in Java. Let's say Product products[].
Each of those products have a price, for example, product.getPrice().
What's the best way I can order that product array by the price so I can call, products[0] for the most expensive product and products[products.length-1] for the least expensive?
Something like this:
Arrays.sort(products, new Comparator<Product>() {
#Override
public int compare(Product p1, Product p2) {
if (p1.getPrice() > p2.getPrice()) return -1;
if (p1.getPrice() < p2.getPrice()) return 1;
return 0;
}
});
I would recommend using an ArrayList to do this. Index them in order from most expensive to least expensive using a for loop, like this:
ArrayList products = new ArrayList();
final int MAX_PRICE = 9999; // Or whatever the maximum price should be
for (int i = MAX_PRICE, i > 0, i--) {
if (product.getPrice() == i) {
products.add(product);
}
}
You can also use Comparable interface to override compareTo method with template T as Products.
Then use the following code,
Collections.sort(products);
You can always use Oracle docs for knowing about Comparable Interface at docs.oracle.com

Can we sort a Set by keys and values in Map?

i have a class Car representing name and IDs of cars:
public class Car {
String name;
int ID;
}
and another class representing races in which i need to sort the cars by their order in race:
public class Race {
private Set<Car> cars = new TreeSet<>();
private Map<Integer, Integer> races = new TreeMap<>();//key represents the order in race, value represents the ID of a car, so i need to sort cars by the keys in races
...
public Collection getSortedCars() { ??? }
}
-any ideas how to get sorted cars? thanks much
EDIT: Im sorry, i used very bad example with values, so heres it with identifiers, i hope you get what i need..
I would not do this with a SortedSet, even though a custom Comparator could be used. The reason is because the races could be modified and thus invalidate any structure inside the TreeSet making the behavior "unpredictable".
Instead, I would make getSortedCars first get a sequence (e.g. a List) from the Set, and then sort and return such a sequence.
The actual sorting is "trivial" with Collections.sort and a custom Comparator as this is really a "sort by" operation, for instance:
class CompareCarsByWins implements Comparator<Car> {
Map<Car,Integer> wins;
public CompareCarsByWins(Map<Car,Integer> wins) {
this.wins = wins;
}
public int compareTo (Car a, Car b) {
// Actual code should handle "not found" cars as appropriate
int winsA = wins.get(a);
int winsB = wins.get(b);
if (winsA == winsB) {
// Tie, uhm, let's .. choose by name
return a.getName().compareTo(b.getName());
} else {
// Sort most wins first
return winsB - winsA;
}
}
// ..
}
// Usage:
List<Car> results = new ArrayList<Car>(cars);
Collections.sort(results, new CompareCarsByWins(races));

Iterating and processing an ArrayList

I have a List of objects. I want to iterate through this list of objects and process some subsets of objects based on a condition and finally create a new list of objects with some processed objects being eliminated.
What is the best way to do this.?
Example:
Actual object : List<Cars>
Iterate through this list and find Cars with same speed.
In that smaller set of Cars, the ones which are of same model are to be eliminated.
Finally after elimination I get the new list.
The Google Guava libraries have:
Iterables.filter(cars, new Predicate<Car>() {
#Override
public boolean apply(Car car) {
//return true or false depending on whether you
// want this car to remain in the list
}
}
You can also use an intermediate Set - i.e.
cars = new ArrayList<Car>(new HashSet<Car>(cars));
where you have properly implemented hashCode and equals. This option is viable if this is the identity of your car.
You can also use an iterator:
for (Iterator<Car> it = cars.iterator(); it.hasNext();) {
Car car = it.next();
if (conditions here) {
it.remove();
}
}
By the way, I'm aware that the above examples don't solve your problem completely - you should still consider what to iterate within the outer loops.
If you are looking to do custom equals comparing, then you should define a Comparator<Car> and then just loop through the Cars.
List<Car> originalList;
Comparator<Car> c = new CarSpeedComparator();
List<Car> result = carFilter(originalList, c);
/// Below is the filter method
public static List<Car> carFilter(List<Car> original, Comparator<Car> comp)
List<Car> result = new ArrayList<Car>();
// Process each car
for (Car car: original) {
boolean containsC = false;
// now we check each car in the result
// to see if we already have an equivalent car
for (int i = 0; i < result.size(); i++) {
// if the two cars are equivalent under the rules
// then we already have that car in the list
if (comp.compare(result.get(i), car) == 0) {
containsC = true;
break;
}
}
// if the result does not contain an equivalent car,
// add it to the list
if (!containsC) result.add(car)
}
return result;
}
//// Implementation of one of the necessary comparators
public class CarSpeedComparator implements Comparator<Car> {
public int compare(Car c1, Car c2) {
return c1.getSpeed() - c2.getSpeed();
}
}
The resulting list will only contain one car of each speed.
It sounds like what you might want to do first is index the cars in your list by speed. Once you've done that, it might be easier to do the rest of the processing you're looking for. Guava's Multimaps are good for this:
ImmutableListMultimap<Integer, Car> speedIndex = Multimaps.index(cars,
new Function<Car, Integer>() {
public Integer apply(Car from) {
return from.getSpeed();
}
});
Now speedIndex will be a multimap that lets you do something like this:
for (Integer speed : speedIndex.keySet()) {
ImmutableList<Car> carsWithSpeed = speedIndex.get(speed);
// Do stuff
}
This gives you groupings of all cars in the original list that have the same speed. You could then do whatever processing on them you wanted. You might want to index this group of cars by model, giving you groupings of cars that have both the same speed and model. You could then remove those cars from the original list if you wanted. Alternatively, if you don't want to modify the original list at all but just get a copy of the list with a set of cars removed, you could add each car to be removed to a Set, then get the copy with those cars removed like this:
Set<Car> carsToRemove = ...;
List<Car> filteredList = Lists.newArrayList(Iterables.filter(cars,
Predicates.not(Predicates.in(carsToRemove))));
If you did this repeatedly on big lists, you'd want to be more efficient. Keep a list of objects, but also keep separate lists for each model of car; Hashtable<String, List> models. That way, you already have the model part done for future sorts. It takes slightly more memory, but notably less time to search through.
To me it looks like the OP just wants a unique set of (model,speed) pair. If so, here is a easy way to do it:
class Car {
private final String model;
private final int speed;
public int hashCode(){
return model.hashCode() + speed;
}
public boolean equals(Object obj){
//check on null/different class omitted.
Car other = (Car)obj;
return this.model.equals(obj.model) && this.speed == other.speed;
}
}
then
Set<Car> cars = new HashSet<Car>(originalListOfCars);

Categories