如何计算HashMap中唯一值的数量?

时间:2017-09-12 06:19:47

标签: java arraylist hashmap

我在这里看到了很多关于如何使用ArrayList和HashMaps的好解决方案,但重点是我仍然无法解决我的问题。

所以,这个想法是很少有人喝啤酒,葡萄酒和可乐。所以,它看起来像(例如):

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

我的想法是创建一个对象Person(String name,String drink)。然后我将所有人都放到ArrayList中。之后我创建了HashMap,并希望在键不存在的情况下添加一个新Person,如果key已经存在则增加到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的想法? 非常感谢!

8 个答案:

答案 0 :(得分:7)

在Person类

中覆盖hashcode和equals方法

答案 1 :(得分:5)

如果您可以使用Java 8流,这是一个聪明的解决方案:

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

答案 2 :(得分: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);
        }
   }

答案 3 :(得分:1)

类中覆盖等于 hascode 方法是解决您问题的方法。

假设你有Person类参数 name drink ,那么你可以使用像eclipse这样的IDE为你生成hashcode和equals方法

见下面的代码:

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

答案 4 :(得分:1)

您必须在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

希望它会对你有所帮助。

答案 5 :(得分: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()));
        }
    }
}

答案 6 :(得分:0)

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

我想这样说:

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

答案 7 :(得分:0)

首先,我建议你照顾好自己的名字。在你的情况下,真正的关键是订单不是一个人(因为史蒂夫可乐和史蒂夫葡萄酒不同,你不应该把它命名为人)。

之后:containsKey将使用hashcode方法,如果你不在类中覆盖它,它将从Object类继承。 Object类的哈希码可能会为您的实例提供不同的哈希码,因此您应该在类中覆盖它,例如如果您连接名称和饮料(这是订单的唯一标识符)并在该字符串上调用哈希码方法,则可以创建可接受的哈希码方法。