2016-04-11 24 views
0

だから、私は同じキーで異なる値を持つすべてのペットショップの合計を計算するこのプログラムを持っています。しかし、今、私は同じキーを持つ各ペットショップの平均を計算したいと思います。私は、ペットショップがarraylistに何回含まれているかを知るためにカウンターを使うことを考えていました。しかし、それは動作しません。各ループごとに別のものを実行する必要がありますか?同じキーでハッシュマップ値の平均を計算する方法

public class AverageCost { 

    public void calc(ArrayList<Pet> pets) { 

     Map<String, Double> hm = new HashMap<>(); 

     for (Pet i : pets) { 
      String name = i.getShop(); 
      // If the map already has the pet use the current value, otherwise 0. 
      double price = hm.containsKey(name) ? hm.get(name) : 0; 
      price += i.getPrice(); 
      hm.put(name, price); 

     } 
     System.out.println(""); 
     for (String key : hm.keySet()) { 
      System.out.printf("%s: %s%n", key, hm.get(key)); 
     } 

    } 
+7

を分割するCollections.frequencyを使用することができます。 'HashMap'にキーを重複させることはできません。したがって、「同じキーを持つ各ペットショップの平均を計算したい」と言うと、キーごとに1つのエントリしか存在しません。 – Austin

+0

累積価格とペット数の両方を保持するために、複合価値オブジェクトを数えたり使用したりするために2番目のマップを導入することができます: 'Map hm' – hoaz

+0

ハッシュマップに平均を保存しようとしているのですか? ? – marcellorvalle

答えて

1

あなたが求めている何を計算するためのアルゴリズムであります今までに蓄積した用語の数を保存せずに累積移動平均を計算します。私はこれが可能だとは思わない(例えば、今のところ用語の数が必要なところはhttps://en.wikipedia.org/wiki/Moving_average#Cumulative_moving_average参照)。私の提案は、2回のパスを使用することです - 最初に数値を格納し、2番目に平均を計算します。

public void calc(List<Pet> pets) { 
    // First pass 
    Map<String, List<Double>> firstPass = new HashMap<>(); 
    for (Pet pet : pets) { 
     String name = pet.getShop(); 
     if (firstPass.containsKey(name)) { 
      firstPass.get(name).add(pet.getPrice()); 
     } else { 
      List<Double> prices = new ArrayList<>(); 
      prices.add(pet.getPrice()); 
      firstPass.put(name, prices); 
     } 
    } 

    // Second pass 
    Map<String, Double> results = new HashMap<>(); 
    for (Map.Entry<String, List<Double>> entry : firstPass.entrySet()) { 
     Double average = calcAverage(entry.getValue()); 
     results.put(entry.getKey(), average); 
     // Print results 
     System.out.printf("%s: %s%n", entry.getKey(), average); 
    } 
} 

private double calcAverage(List<Double> values) { 
    double result = 0; 
    for (Double value : values) { 
     result += value; 
    } 
    return result/values.size(); 
} 
1

あなたは、カウントのための第2のマップを導入したり、ペットの両方の累積価格と番号を保持するために、あなたのマップ内の化合物の値オブジェクトを使用することができます。

Map<String, PetStatistics> hm = new HashMap<>(); 
for (Pet i : pets) { 
    String name = i.getShop(); 
    // If the map already has the pet use the current value, otherwise 0. 

    PetStatistics stats = hm.get(name); 
    if (stats == null) { 
     stats = new PetStatistics(0, 0); // count and price 
     hm.put(name, stats); 
    } 
    stats.addPrice(i.getPrice()); 
    stats.incrementCount(); 
} 
+0

'put'の中で' put() 'を動かしてください。 – Andreas

+0

ああ、いいキャッチ。ありがとう – hoaz

+0

提案: 'PetStatistics'はカウンタ自体をインクリメントする必要があります。 'getTotalPrice()'、 'getMaxPrice()'、 'getMinPrice()'、 'getAveragePrice()'、 'getPriceCount()'、およびその他のすべてのメソッドをサポートするには、単純な 'addPrice()価格のセットには他の統計が必要です。 – Andreas

1

あなたは、私はあなたの質問で少し混乱しているの発生の数を取得し、全体の合計に

for (String key : hm.keySet()) { 
    int w = Collections.frequency(pets, new Pet(key)); 
    System.out.printf("%s: %s%n", key, hm.get(key)/w); 
} 
関連する問題