Java 键中有多个值的集合

Java 键中有多个值的集合,java,collections,Java,Collections,我正在寻找一个集合类型的数据结构来实现以下内容。假设我有一门课是这样的: class Person() { String homeTown; // key String sex; // key String eyeColour; // key String name; long height; // other stuff.... } Map<String, HashSet<Person>> = new Ha

我正在寻找一个集合类型的数据结构来实现以下内容。假设我有一门课是这样的:

class Person() {

    String homeTown;   // key
    String sex;  // key 
    String eyeColour;  // key
    String name;
    long height;

    // other stuff....
}
Map<String, HashSet<Person>> = new HashMap<String, HashSet<Person>>;
我正在处理多人对象。我想把它们组织成一组,每组都包含具有相同家乡、性别和眼睛颜色的人物对象。目前,我正在实施类似的措施:

class Person() {

    String homeTown;   // key
    String sex;  // key 
    String eyeColour;  // key
    String name;
    long height;

    // other stuff....
}
Map<String, HashSet<Person>> = new HashMap<String, HashSet<Person>>;
Map=newhashmap;
这里的关键是家乡、性别和眼睛的颜色。这可以工作,但似乎有点不整洁-有人能推荐一个更优雅的解决方案或更好的数据结构来使用吗,谢谢?

您可以使用Sets.filter方法来过滤person对象

例如:

人员类别:

public class Person {
 String name;
 String hometown;
 int age;

 public Person(String name, String hometown, int age) {
  this.name = name;
  this.age = age;
  this.hometown = hometown;
 }

 @Override
 public int hashCode() {
  int hash = 17;
  hash = 37 * hash + name.hashCode();
  hash = 37 * hash + hometown.hashCode();
  hash = 37 * hash + age;
  return hash;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  Person p;
  if (obj instanceof Person)
   p = (Person) obj;
  else
   return false;

  if (this.name.equals(p.name) && this.hometown.equals(p.hometown)
    && this.age == p.age)
   return true;

  return false;
 }

 @Override
 public String toString() {
  StringBuilder b = new StringBuilder();
  b.append("[name = ").append(name).append("\n");
  b.append("home town = ").append(hometown).append("\n");
  b.append("age = ").append(age).append("]");
  return b.toString();
 }

}
public class TestGuavaFilter {
 public static void main(String[] args) {
  Set<Person> set = new HashSet<Person>();

  set.add(new Person("emil", "NY", 24));
  set.add(new Person("Sam", "NY", 50));
  set.add(new Person("george", "LA", 90));
  System.out.println(Sets.filter(set, new FilterHomeTown("NY")));
 }
}

class FilterHomeTown implements Predicate<Person> {
 String home;

 public FilterHomeTown(String home) {
  this.home = home;
 }

 @Override
 public boolean apply(Person arg0) {

  if (arg0.hometown.equals(this.home))
   return true;
  return false;
 }

}
TestGuavaFilter类:

public class Person {
 String name;
 String hometown;
 int age;

 public Person(String name, String hometown, int age) {
  this.name = name;
  this.age = age;
  this.hometown = hometown;
 }

 @Override
 public int hashCode() {
  int hash = 17;
  hash = 37 * hash + name.hashCode();
  hash = 37 * hash + hometown.hashCode();
  hash = 37 * hash + age;
  return hash;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  Person p;
  if (obj instanceof Person)
   p = (Person) obj;
  else
   return false;

  if (this.name.equals(p.name) && this.hometown.equals(p.hometown)
    && this.age == p.age)
   return true;

  return false;
 }

 @Override
 public String toString() {
  StringBuilder b = new StringBuilder();
  b.append("[name = ").append(name).append("\n");
  b.append("home town = ").append(hometown).append("\n");
  b.append("age = ").append(age).append("]");
  return b.toString();
 }

}
public class TestGuavaFilter {
 public static void main(String[] args) {
  Set<Person> set = new HashSet<Person>();

  set.add(new Person("emil", "NY", 24));
  set.add(new Person("Sam", "NY", 50));
  set.add(new Person("george", "LA", 90));
  System.out.println(Sets.filter(set, new FilterHomeTown("NY")));
 }
}

class FilterHomeTown implements Predicate<Person> {
 String home;

 public FilterHomeTown(String home) {
  this.home = home;
 }

 @Override
 public boolean apply(Person arg0) {

  if (arg0.hometown.equals(this.home))
   return true;
  return false;
 }

}
公共类TestGuavaFilter{
公共静态void main(字符串[]args){
Set=newhashset();
增加(新的人(“埃米尔”,“纽约”,24));
增加(新的人(“山姆”,“纽约”,50));
添加(新人物(“乔治”,“洛杉矶”,90));
System.out.println(set.filter(set,新FilterHomeTown(“NY”)));
}
}
类FilterHomeTown实现谓词{
串回家;
公共过滤器住宅(串住宅){
this.home=家;
}
@凌驾
公共布尔值应用(人员arg0){
if(arg0.home.equals(this.home))
返回true;
返回false;
}
}

使用过滤器的优点是,您可以以任何方式过滤Person对象,假设您只想使用home town而不使用其他两个属性进行过滤,这将很有帮助。此外,由于guava的过滤器只生成真实集合的视图,您可以节省内存。

您可以重新构造类,使键显式。这比简单地连接键值更健壮,并且避免了在希望将Person实例存储在映射中时的任何额外对象创建开销,因为您已经急切地提前创建了键

public class Person {
  public class Key {
    private final String homeTown;
    private final String sex;
    private final String eyeColour;

    public Key(String homeTown, String sex, String eyeColour) { ... }

    public boolean equals(Object o) { /* Override to perform deep equals. */ }
    public int hashCode() { /* Could pre-compute in advance if the key elements never change. */ }
  }

  private final Key key;
  private final String name;
  private final long height;

  public Person(String homeTown, String sex, String eyeColour, String name, long height) {
    this.key = new Key(homeTown, sex, eyeColour);
    this.name = name;
    this.height = height;
  }

  public Key getKey() {
    return key;
  }

  public String getName() { return name; }
  public long getHeight() { return height; }
}

创建一个对象来为密钥建模。例如
类PersonKey{String homightry,sex,eyecolor}
(为简洁起见省略了getter和setter)

为此对象实现
equals
hashCode
方法

将此对象用作
地图中的键

Person
对象中删除属性,或将其替换为对
PersonKey
对象的引用

此外,考虑将你的地图的类型设为以下,即你不需要指定你使用的是什么类型的<代码>设置/代码>作为你的地图的钥匙。< /P>

Map<String, Set<Person>> = new HashMap<String, Set<Person>>();
Map=newhashmap();

而且,如果您使用的是
集合
,那么您还需要为
人员
覆盖
等于和
哈希代码
,否则
集合
无法正确确定两个
人员
对象是否代表同一个人,这是确保集合只包含唯一元素所必需的。

谢谢Adrian,与我实现的Adamski相同的建议(或多或少)我还应该指出,使用字符串来表示性和眼睛颜色可能是个坏主意;你应该考虑使用枚举。类似地,您可能希望在实例化期间检查高度是否为非负,也可能将其重命名为显式;e、 “高度激励”。这只是我为了这个问题而编的一个例子,伙计@dairemac一个快速指针,将散列存储为您的字段之一,并更改hashCode方法以查看散列是否已计算,否则您将反复进行所有计算。嗨,foret,谢谢您的建议。我们看了一下API。我不认为这是我在寻找的-它使用一个集合作为映射值,但它没有给我一个更好的方法来实现映射键,这正是我所要求的。我想我可以把它和亚当斯基和阿德里安·史密斯建议的关键解决方案一起使用。谢谢埃米尔——不过我不确定这是否适合我。您将通过新的FilterHomeTown(“NY”)——我希望将具有相同家乡的元素组合在一起,而不是所有家乡为“NY”或“LA”或其他任何地方的元素。还是我误解了?