2017-09-12 5 views
1

ArrayListとHashMapsを使って作業する方法についてここで素晴らしいソリューションがたくさんありましたが、問題は解決できません。HashMapの一意の値の数を数えるには?

だから、ビール、ワイン、コーラを飲む人はほとんどいないということです。だから、それは、(例えば)以下のようになります。

Steve wine 
Steve cola 
Ben cola 
Frank wine 
Ben cola 
Ben cola 
Frank wine 

最後に、私はそれらのそれぞれが飲んだどのように多くの各ドリンクのグラスカウントする必要があります。だから、答えはそのようになります。

Steve wine 1 
Steve cola 1 
Ben cola 3 
Frank wine 2 

私の考えは、対象者(文字列名、文字列のドリンク)を作成するために入れていました。そして、私はすべての人をArrayListに入れました。その後、私はHashMapを作成し、そこにキーが存在しない場合は新しいPersonを追加したい、キーがすでに存在する場合は1に増やしたいと考えました。

Map<Person, Integer> map = new HashMap<Person, Integer>(); 

    for (Person p : persons) 
    { 
     if (map.containsKey(p)) { 
      map.put(p, map.get(p)+1); 
     } else { 
      map.put(p,1); 
     } 
    } 

これは機能しません。

Steve wine 1 
Steve cola 1 
Ben cola 1 
Frank wine 1 
Ben cola 1 
Ben cola 1 
Frank wine 1 

このような結果が返ってくるだけです。ここでは他のトリックがあるはずです。 HashMapを使用する代わりに、ドリンクの眼鏡を数える方法について他のアイデアを教えてください。 多くの感謝!

+9

PersonクラスでhashCodeとequalsをオーバーライドしましたか? – Eran

+2

[HashSetの複製は2つのオブジェクトが同じであることを認識していないようです](https://stackoverflow.com/questions/3692426/hashset-does-not-seem-to-realize-that-two-objects-are -the-same) – Ferrybig

答えて

5

あなたはここでのJava 8のストリームを使用することができた場合は1つの巧妙なソリューションです:

List<Person> people = Arrays.asList(new Person("Steve", "wine"), new Person("Steve", "cola"), 
      new Person("Ben", "cola"), new Person("Ben", "cola"), new Person("Steve", "wine"), 
      new Person("Steve", "wine")); 

    Map<Person, Long> map = people.stream() 
      .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); 

編集: あなたは静的に、このようなメソッドをインポートすることができ、コードを低下させるために:

import static java.util.stream.Collectors.groupingBy; 
import static java.util.stream.Collectors.counting; 
import static java.util.function.Function.identity; 

とコードは次のようになります。

Map<Person, Long> map = people 
       .stream() 
       .collect(groupingBy(identity(), counting())); 
+0

コードの1行で非常に素晴らしいソリューション!しかし正直なところ、私はこのコード行の中で正確に何が起こっているのか理解していません。 – Boris

1

Personオブジェクトをキーとして間違えています。

人名、文字列をキーとして保存する必要があります。正常に動作します。

Map<String, Integer> map = new HashMap<>(); 

    for (Person p : persons) 
    { 
     if (map.containsKey(p.getName())) { 
      map.put(p.getName(), map.get(p)+1); 
     } else { 
      map.put(p.getName(),1); 
     } 
    } 
+0

その 'Map 'はそれほどうまくありませんか? – nullpointer

+0

いいえ、そうではありません.2つの選択肢があります。1.文字列(名前)をキーとして使用します。または。 2. PersonをキーとしてPersonを使用しますが、Personクラスのhashcode()メソッドとequals()メソッドをオーバーライドします。 –

+0

@Seelenvirtuoseを再度確認してください。親切に-1を元に戻してください。訂正するのではなく、答えを下ろすことです。 –

6

上書きハッシュコードとあなたのPersonクラスに

0
int count = Collections.frequency("your collection", "Your Value"); 

のequalsメソッドを、私はそのように言うことを意味:

ArrayList<String> list = new ArrayList<>(); 
list.add("Steve wine"); 
list.add("Steve cola"); 
list.add("Ben cola"); 
list.add("Frank wine"); 
list.add("Ben cola"); 
list.add("Ben cola"); 
list.add("Frank wine"); 

System.out.println(Collections.frequency(list, "Steve wine")); 

System.out.println(Collections.frequency(list, "Ben cola")); 
+0

「あなたの価値」とは何ですか?私は人々の名前や彼らが前もって飲むものは知らない。 – Boris

+0

入力は「Steve wine」 –

+0

私は解決策を更新しました –

0

まず、私はあなたのネーミング・世話をするためにあなたをお勧めします。本当にあなたの場合の鍵は、人ではなく注文です(スティーブ・コーラとスティーブ・ワインは違うので、それを人物と名付けてはいけません)。

これ以降:containsKeyは、クラスでオーバーライドしないと、Objectクラスから継承されるhashcodeメソッドを使用します。 Objectクラスのハッシュコードは、おそらくインスタンスに異なるハッシュコードを提供するので、クラス内でオーバーライドする必要があります。名前と飲料(注文の一意の識別子)を連結し、その文字列に対してハッシュコードメソッドを呼び出すと、受け入れ可能なハッシュコードメソッドを作成できます。 hascodeあなたクラスの equalsメソッドをオーバーライド

1

はあなたの問題の解決策です。

public class Person { 
     private String name; 
     private String drink; 

     public String getName() { 
      return name; 
     } 

     public void setName(String name) { 
      this.name = name; 
     } 

     public String getDrink() { 
      return drink; 
     } 

     public void setDrink(String drink) { 
      this.drink = drink; 
     } 

     @Override 
     public int hashCode() { 
      final int prime = 31; 
      int result = 1; 
      result = prime * result + ((drink == null) ? 0 : drink.hashCode()); 
      result = prime * result + ((name == null) ? 0 : name.hashCode()); 
      return result; 
     } 

     @Override 
     public boolean equals(Object obj) { 
      if (this == obj) 
        return true; 
      if (obj == null) 
        return false; 
      if (getClass() != obj.getClass()) 
        return false; 
      Person other = (Person) obj; 
      if (drink == null) { 
        if (other.drink != null) 
         return false; 
      } else if (!drink.equals(other.drink)) 
        return false; 
      if (name == null) { 
        if (other.name != null) 
         return false; 
      } else if (!name.equals(other.name)) 
        return false; 
      return true; 
     } 
} 
+0

はい、今は動作します。ありがとう!私はJavaプログラミングの初心者です。以前はHashCodeメソッドをオーバーライドしようとしたことはありません。私はこれがそのような問題のあらゆる種類のための良い、より一般的な解決策だと思います。 – Boris

1

:あなたは、パラメータドリンクでPersonクラスを持っている、あなたはハッシュコードを生成するために、EclipseのようないくつかのIDEを使用することができますし、あなた

するための方法に等しいコードの下に表示さ仮定

PersonクラスでequalsメソッドとhashCodeメソッドをオーバーライドする必要があります。以下のサンプルコードです:この後

class Person { 

    private String name; 
    private String drink; 

    public Person(String name, String drink) { 
    super(); 
    this.name = name; 
    this.drink = drink; 
    } 

    @Override 
    public int hashCode() { 

    return this.getName().hashCode(); 
    } 

    @Override 
    public boolean equals(Object obj) { 

    if (obj == this) 
     return true; 

    if (!(obj instanceof Person)) { 
     return false; 
    } 
    Person person = (Person) obj; 

    return person.getName().equals(this.name); 
    } 
    ....getters and setters 
    ....toString method 
} 

はあなたのコードを実行しようとした場合、それはコードの下のために私のために確実に出力を動作しますが、た

Map<Person, Integer> map = new HashMap<>(); 

    for (Person p : persons) 
    { 
     if (map.containsKey(p)) { 
      map.put(p, map.get(p)+1); 
     } else { 
      map.put(p,1); 
     } 
    } 

    for(Map.Entry<Person, Integer> person : map.entrySet()){ 
     System.out.println(person.getKey()+" "+person.getValue()); 
    } 

出力:

Person [name=Steve, drink=wine] 2 
Person [name=Ben, drink=cola] 3 
Person [name=Frank, drink=wine] 2 

それがあなたを助けてくれることを願っています。

1

キーは、ハッシュマップまたはディクショナリ(C#)で一意である必要があります。このケースでは、キー自体を挿入する際に名前とドリンクを組み合わせる必要があります。ここでC#でソリューションを提供する。それが役に立てば幸い。

public class Person 
{ 
    public string Name { get; set; } 
    public string Drink { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<Person> persons = new List<Person>(); 
     persons.Add(new Person() { Name = "Steve", Drink = "Tea" }); 
     persons.Add(new Person() { Name = "Bell", Drink = "Milk" }); 
     persons.Add(new Person() { Name = "Bell", Drink = "Milk" }); 
     persons.Add(new Person() { Name = "Bell", Drink = "Milk" }); 
     persons.Add(new Person() { Name = "Steve", Drink = "Milk" }); 
     Dictionary<string, int> output = new Dictionary<string, int>(); 
     foreach(var p in persons) 
     { 
      string key = p.Name + ":" + p.Drink; 
      if(output.ContainsKey(key)) 
      { 
       output[key]++; 
      } 
      else 
      { 
       output.Add(key,1); 
      } 
     } 
     foreach(var k in output) 
     { 
      string[] split = k.Key.Split(':'); 
      Console.WriteLine(string.Format("{0} {1} {2}", split[0],split[1],k.Value.ToString())); 
     } 
    } 
} 
+0

OPで動作する言語ではありません.Javaでは実装が異なることを考慮すると、彼は助けにならないでしょう。 – Assafs

関連する問題