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”或其他任何地方的元素。还是我误解了?