2017-09-12 1 views
1

J'ai vu beaucoup de bonnes solutions ici sur la façon de travailler avec ArrayList et HashMaps, mais le fait est que je ne peux toujours pas résoudre mon problème. Donc, l'idée est qu'il y a peu de gens qui boivent de la bière, du vin et du coca cola. Alors, ça ressemble à ça (par exemple):Comment compter le nombre de valeurs uniques dans HashMap?

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

En fin de compte, je dois compter combien de verres de chaque boisson chacun d'eux a bu. Donc, la réponse devrait ressembler à ce que:

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

Mon idée était de mettre à créer une personne d'objet (String name, boisson String). Ensuite, je mets toutes les personnes à ArrayList. Après cela, j'ai créé HashMap et je voulais y ajouter une nouvelle personne si la clé n'existe pas, et à incrémenter à 1 si la clé existe déjà.

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

Cela ne fonctionne pas. Il me renvoie juste le résultat comme ceci:

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

Ainsi, si je comprends bien cela devrait être un autre tour ici. Peut-être que vous pourriez également dire d'autres idées sur la façon de compter les verres des boissons au lieu d'utiliser HashMap? Merci beaucoup!

+9

Avez-vous remplacé hashCode et est égal à la classe Person? – Eran

+2

Un doublon possible de [HashSet ne semble pas réaliser que deux objets sont identiques] (https://stackoverflow.com/questions/3692426/hashset-does-not-seem-to-realize-that-two-objects-are -the-same) – Ferrybig

Répondre

5

Si vous pouvez utiliser Java 8 flux ici est une solution intelligente:

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

Edit: Pour diminuer le code que vous pouvez importer les méthodes statiquement comme ceci:

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

et alors le code ressemble à ceci:

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

Très belle solution juste en 1 ligne de code! Mais honnêtement, je ne comprends pas ce qui se passe exactement dans cette ligne de code. – Boris

1

Vous commettez une erreur en stockant Person Objet en tant que clé.

Vous devez stocker le nom de la personne, une chaîne en tant que clé et cela fonctionnera correctement.

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

C'est un 'Map ', n'est-ce pas bien alors? – nullpointer

+0

Non, ce n'est pas, vous avez deux choix, 1. utiliser la chaîne (nom) comme une clé. ou. 2. Utilisez Person comme clé mais overirde la méthode hashcode() et equals() dans la classe Person. –

+0

@Seelenvirtuose s'il vous plaît vérifier à nouveau, sa mise à jour. et bien vouloir rétablir votre -1. au lieu de corriger vous downvoting une réponse. –

6

hashcode Ecraser et égale méthode dans votre classe Person

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

je voulais dire comme ça:

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

Qu'est ce que c'est "Votre Valeur"? Je ne connais pas les noms des gens ou ce qu'ils boivent avant. – Boris

+0

entrée serait «Steve vin» –

+0

J'ai mis à jour la solution –

0

D'abord, je vous recommande de prendre soin de vos denominations. Ce qui est vraiment la clé dans votre cas, c'est une commande pas une personne (puisque Steve Cola et Steve Wine sont différents, vous ne devriez pas le nommer comme une personne). Après cela: containsKey utilisera la méthode hashcode qui sera héritée de la classe Object si vous ne la surchargez pas dans votre classe. Le hashcode de la classe Object fournira probablement un hashcode différent pour vos instances, vous devrez donc le remplacer dans votre classe, par exemple. vous pouvez créer une méthode hashcode acceptable si vous concattez le nom et la boisson (qui est votre identifiant unique pour une commande) et invoquez une méthode hashcode sur cette chaîne.

1

Redéfinition méthode equals et hascode dans votre classe Personne est la solution à votre problème.

en supposant que vous avez la classe Person avec le paramètre nom et boisson, alors vous pourriez utiliser certains IDE comme Eclipse pour générer hashcode et méthode Equals pour vous

voir ci-dessous le code:

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

Oui, maintenant ça marche. Merci! Je suis nouveau à la programmation Java et je n'ai jamais essayé de remplacer la méthode HashCode auparavant. Je suppose que c'est une bonne et plus générale solution pour n'importe quel genre de problème comme ça. – Boris

1

Vous devez remplacer la méthode equals et hashCode dans la classe Person. Voici l'exemple de code:

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 
} 

Après cela, si vous essayez d'exécuter votre code il fonctionnera à coup sûr pour moi sortie pour ci-dessous le code a été

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

Sortie:

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

J'espère que ça va vous aider.

1

La clé doit être unique dans la carte de hachage ou le dictionnaire (C#). Ce cas en insérant la clé elle-même doit combiner le nom et la boisson. Donner la solution en C# ici. J'espère que cela aide.

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

Ce n'est pas dans la langue dans laquelle fonctionne l'OP - cela ne va pas l'aider, étant donné que dans Java, l'implémentation est différente. – Assafs