Following problem:
I have got a TreeMap with Strings as keys and Collections in form of ArrayLists as values. In the Strings i save Names of customers of a car renting company and in the ArrayLists i have got all the car names they have ever rented. For example:
Smith : [Audi, BMW, Mazda] Miller : [Audi, Ferrari, VW]
Now i built a second TreeMap with Strings as Keys and Integers as Values. The Strings shall be all the car names of the company and the Integers the amount of times they have ever been rented.
How can i easily iterate through the first map to save the amount of rented cars in the second map? The ArrayList inside of the first Map makes me problems.
Thanks for helping!
In this part I put the data into the second Map. course is the name of the first Map and numberOfCars the name of the second.
int helpNumber = 0;
for (Iterator<String> it = course.keySet().iterator(); it.hasNext(); ){
Object key = it.next();
if(course.get(key).contains(chooseName)){
helpNumber++;
}
System.out.println((course.get(key).contains(chooseName)));
}
if(helpNumber == 1) {
numberOfCars.put(chooseName, 1);
} else if(helpNumber > 1) {
int increasing = numberOfCars.get(chooseName);
increasing++;
numberOfCars.put(chooseName, increasing);
}
In the following part I try to print it in that way:
BMW : 3 VW : 2 Audi: 0 Mazda: 0
So the groups of same renting amounts are together and the car names inside of the groups are sorted alphabetically.
System.out.println("+++++++ car popularity +++++++");
Object helpKey = null;
for(Iterator<String> it = numberOfCars.keySet().iterator(); it.hasNext();) {
Object key = it.next();
if (helpKey == null){
helpKey = key;
}
if(numberOfCars.get(key) > numberOfCars.get(helpKey)) {
helpKey = key;
}
}
int maxCount = numberOfCars.get(helpKey);
for(int i = maxCount; i >= 0; i--) {
for(Iterator<String> it = numberOfCars.keySet().iterator(); it.hasNext();) {
Object key = it.next();
if(numberOfCars.get(key) == maxCount) {
System.out.println((String) key + ": " + numberOfCars.get(key));
}
}
}
[I can't comment yet] The code you've presented is quite confusing due to the way you've named the variables. Don't name variables SomeType helpXxx
to indicate you need help with this variable, if your code is presented properly it will be easy for people to distinguish what variables are causing you trouble and why.
The comments you've received are correct in stating that you need to ask a question based on what specific issue you are having rather than "help me get this value". Your specific issue is iterating through the values contained in a Map when the value is of type Collection.
That said, since I need reps to escape new user stack exchange jail here is your solution:
import java.util.*;
public class Test {
public static void main(String[] args) {
String[] customers = {
"Mr PoopyButtHole", "Stealy", "Bird Person"
};
CarBrand audi = new CarBrand("Audi");
CarBrand bmw = new CarBrand("BMW");
CarBrand mazda = new CarBrand("Mazda");
CarBrand vw = new CarBrand("VW");
CarBrand ferrari = new CarBrand("Ferrari");
// First Map: Customers paired with car brands they've rented
SortedMap<String, List<CarBrand>> customerRentals =
new TreeMap<String, List<CarBrand>>();
// --- Fill the first map with info ---
// For customer Mr PoopyButtHole
List<CarBrand> mrPBHRentals = new ArrayList<>();
Collections.addAll(mrPBHRentals, audi, bmw, mazda);
customerRentals.put(customers[0], mrPBHRentals);
// For customer Stealy
List<CarBrand> stealyRentals = new ArrayList<>();
Collections.addAll(stealyRentals, bmw, mazda, vw);
customerRentals.put(customers[1], stealyRentals);
// For customer Bird Person
List<CarBrand> birdPersonRentals = new ArrayList<>();
Collections.addAll(birdPersonRentals, audi, bmw, mazda, ferrari);
customerRentals.put(customers[2], birdPersonRentals);
// First Map contains 10 occurences of car brands across all the individual
// arraylists paired to a respective customer
// Second Map: Car brands paired with the amount of times they've been
// rented
// You don't actually need the second map to be a TreeMap as you want to
// rearrange the results into your desired format at the end anyway
Map<CarBrand, Integer> carBrandRentalCounts = new HashMap<>();
// Place each CarBrand into carBrandRentalCounts and initialize the counts
// to zero
carBrandRentalCounts.put(audi, 0);
carBrandRentalCounts.put(bmw, 0);
carBrandRentalCounts.put(mazda, 0);
carBrandRentalCounts.put(vw, 0);
carBrandRentalCounts.put(ferrari, 0);
// Get all the values (each ArrayList of carbrands paired to a customer) in
// the first map
Collection<List<CarBrand>> values = customerRentals.values();
// Iterate through 'values' (each ArrayList of car brands rented)
int total = 0;
for(List<CarBrand> aCustomersRentals : values)
for(CarBrand brand : aCustomersRentals) {
// Get the current count for 'brand' in the second map
Integer brandCurrentCount = carBrandRentalCounts.get(brand);
// Increment the count for 'brand' in the second map
Integer newBrandCount = brandCurrentCount+1;
carBrandRentalCounts.put(brand, newBrandCount);
total++;
}
// Init. a List with the entries
Set<Map.Entry<CarBrand,Integer>> entries = carBrandRentalCounts.entrySet();
List<Map.Entry<CarBrand,Integer>> listOfEntries =
new ArrayList<Map.Entry<CarBrand,Integer>>(entries);
// Sort the entries with the following priority:
// 1st Priority: Highest count
// 2nd Priority: Alphabetical order
// NOTE: CustomSortingComparator implements this priority
Collections.sort(listOfEntries, new CustomSortingComparator());
// Print the results
System.out.println("Count of rentals for each car brand:");
for(Map.Entry<CarBrand, Integer> entry : listOfEntries)
System.out.println(" " + entry.getKey() + " --> " + entry.getValue());
System.out.println("Total:" + total);
// Verify that our custom sorted entries are indeed being sorted correctly
// Change the counts to be all the same
for(Map.Entry<CarBrand, Integer> entry : entries)
entry.setValue(10);
// Resort the entries
Collections.sort(listOfEntries, new CustomSortingComparator());
// Print with the test entries
System.out.println();
System.out.println("With test entries where all counts are the same:");
for(Map.Entry<CarBrand, Integer> entry : listOfEntries)
System.out.println(" " + entry.getKey() + " --> " + entry.getValue());
System.out.println("Total:" + total);
// Change the counts so that the ordering is the alphabetically highest
// brands followed by the lowest
for(int i = listOfEntries.size()-1; i >= 0; i--)
listOfEntries.get(i).setValue(i);
// Resort the entries
Collections.sort(listOfEntries, new CustomSortingComparator());
// Print with the test entries
System.out.println();
System.out.println("with test entries where the \"bigger\" car brands " +
"alphabetically have higher counts:");
for(Map.Entry<CarBrand, Integer> entry : listOfEntries)
System.out.println(" " + entry.getKey() + " --> " + entry.getValue());
System.out.println("Total:" + total);
}
}
class CustomSortingComparator
implements Comparator<Map.Entry<CarBrand,Integer>> {
public int compare(Map.Entry<CarBrand, Integer> entry1,
Map.Entry<CarBrand, Integer> entry2) {
CarBrand brand1 = entry1.getKey();
CarBrand brand2 = entry2.getKey();
int brandResult = brand1.compareTo(brand2);
Integer count1 = entry1.getValue();
Integer count2 = entry2.getValue();
int countResult = count1.compareTo(count2);
return
countResult > 0 ?
-1 : countResult < 0 ?
1 : brandResult < 0 ? // <-- equal counts here
-1 : brandResult > 1 ?
1 : 0;
}
}
// DONT WORRY ABOUT THIS CLASS, JUST MAKES IT EASIER TO IDENTIFY WHAT'S GOING
// ON IN THE FIRST MAP
class CarBrand implements Comparable<CarBrand> {
public final String brand;
public CarBrand(String brand) { this.brand = brand; }
@Override
public int compareTo(CarBrand carBrand) {
return brand.compareTo(carBrand.brand);
}
@Override
public boolean equals(Object o) {
// IF o references this CarBrand instance
if(o == this) return true;
// ELSE IF o is of type CarBrand, perform equality check on field 'brand'
else if(o instanceof CarBrand) {
CarBrand obj = (CarBrand)o;
// IF the brands are equal, o is equal to this CarBrand
if(brand.equals(obj.brand)) return true;
}
return false;
}
@Override
public String toString() { return brand; }
@Override
public int hashCode() { return brand.hashCode(); }
}
Count of rentals for each car brand:
BMW --> 3
Mazda --> 3
Audi --> 2
Ferrari --> 1
VW --> 1
Total:10
With test entries where all counts are the same:
Audi --> 10
BMW --> 10
Ferrari --> 10
Mazda --> 10
VW --> 10
Total:10
with test entries where the "bigger" car brands alphabetically have higher counts:
VW --> 4
Mazda --> 3
Ferrari --> 2
BMW --> 1
Audi --> 0
Total:10
This compiles and runs without any changes or extra imports.
It looks like your overthinking how to get the desired result or you don't have a good grasp of the Map class and thus are just hacking your way through. We all do it... and we all hate ourselves 12 hours later for doing it. Think it through :)
Identify the main problem: Iterating through all the values contained in the first map.
Don't get caught up with implementation details before you've grasped the problem, aka:
The point of no return in your code is when you attempted to count the occurrences of car brands in the values of the first map and store these counts into the second map. Here's a "recipe" with code hints to help you handle it.
Collection<ArrayList<String>> eachCustomersRentals = CustomerRentals.values();
for(ArrayList<String> aCustomersRentals : eachCustomersRentals) {...}
{...}
first nest an enhanced for-each loop that iterates over
aCustomersRentalsThe sorting that you want to achieve for the output will be very very messy if you don't know how to implement a custom Comparator to abstract the details away for you. If you must do this sorting, take a good look at the Comparator and Comparable interfaces documentation (Google Comparator/Comparable ) and then analyse how I implemented it.