簡體   English   中英

用Java遍歷Maps

[英]Iterating through Maps in Java

以下問題:

我有一個以字符串為鍵的TreeMap和以ArrayLists的形式為值的Collections。 在字符串中,我保存了租車公司的客戶名稱,在ArrayList中,我得到了他們曾經租過的所有汽車名稱。 例如:

史密斯:[奧迪,寶馬,馬自達]米勒:[奧迪,法拉利,大眾]

現在,我用字符串作為鍵和整數作為值構建了第二個TreeMap。 字符串應為公司的所有汽車名稱,整數應為租用的時間。

我如何輕松遍歷第一張地圖以節省第二張地圖中的租車數量? 第一個Map內部的ArrayList讓我感到麻煩。

感謝您的幫助!

在這一部分中,我將數據放入第二張地圖。 當然是第一個Map的名稱,而numberOfCars是第二個Map的名稱。

        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);
        }

在以下部分中,我嘗試以這種方式進行打印:

寶馬:3大眾:2奧迪:0馬自達:0

因此,相同租金金額的組在一起,並且組內的汽車名稱按字母順序排序。

    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));
            }
        }
    }

[我無法評論]由於命名變量的方式,您所呈現的代碼相當混亂。 不要命名變量SomeType helpXxx來指示您需要此變量的幫助,如果正確顯示您的代碼,人們將很容易區分是什么變量導致了您的麻煩以及原因。

您收到的評論正確無誤,表明您需要根據遇到的具體問題提出問題,而不是“幫助我獲得此價值”。 當值的類型為Collection時,您的特定問題是遍歷Map中包含的值。

就是說,由於我需要代表逃避新的用戶堆棧交換監獄,因此這是您的解決方案:

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

這將編譯並運行,而無需任何更改或額外的導入。

更多信息

您似乎過分思考如何獲得所需的結果,或者您不太了解Map類,因此只是在破解自己的方法。 我們都這樣做了……而且我們都在12小時后討厭自己這樣做。 想一想:)

確定主要問題:遍歷第一個映射中包含的所有值。

在解決問題之前,不要緊跟實現細節,也可以:

  • Map中值V的類型,在這種情況下為ArrayList
  • 正在使用什么類型的地圖

代碼中沒有回報的要點是,當您嘗試在第一張地圖的值中計算汽車品牌的出現次數並將這些計數存儲到第二張地圖中時。 這是帶有代碼提示的“食譜”,可以幫助您進行處理。

  1. 從CustomerRentals獲取所有值(地圖1)
    • Collection<ArrayList<String>> eachCustomersRentals = CustomerRentals.values();
  2. 遍歷每個客戶的租金,存儲每個汽車品牌的總數
    • for(ArrayList<String> aCustomersRentals : eachCustomersRentals) {...}
    • {...}首先嵌套一個增強的for-each循環,該循環遍歷aCustomersRentals
    • 然后,在嵌套循環中,對特定客戶租用的品牌進行計數,並將每個計數存儲在方法范圍內的變量中(也就是外部for-each構造之外)
  3. 初始化第二張地圖
  4. 將每個有其品牌的汽車品牌放入第二張地圖

如果您不知道如何實現自定義比較器來為您提取詳細信息,那么您想要為輸出實現的排序將非常混亂。 如果必須進行這種排序,請仔細閱讀Comparator和Comparable接口文檔(Google Comparator / Comparable),然后分析我如何實現它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM