2012-05-09 69 views
3

我需要按Integer值“level”对java对象集合进行排序。我还需要确定这个集合是否已经通过“title”包含了一个对象。对一个java对象集合按一个值排序并保持唯一值

我相信集合的最佳选择是TreeSet具有一组有序的唯一值。

我与“电平”和对象“标题属性它实现可比像这样:

它覆盖Equals方法(用于检查该对象是否通过已经包含在TreeSet中‘标题’。

代码如下:

@Override 
public boolean equals(Object arg0) { 

    Artifact obj = (Artifact) arg0; 

    if (this.getTitle().equals(obj.getTitle())) { 
     return true; 
    } 

    return false; 
} 

@Override 
public int compareTo(Artifact aThat) { 

    final int BEFORE = -1; 
    final int EQUAL = 0; 
    final int AFTER = 1; 

    if (this == aThat) return EQUAL; 

    if (this.level < aThat.level) return BEFORE; 
    if (this.level > aThat.level) return AFTER; 

    assert this.equals(aThat) : "compareTo inconsistent with equals."; 
    return EQUAL; 
} 

当我尝试值从一个ArrayList与添加到列表中可能重复值的包含似乎不工作,并且对象添加到TreeSet的,无论这是。代码:

TreeSet<Artifact> subsetOfArtifacts = new TreeSet<Artifact>(); 

ArrayList<Artifact> allArtifacts = getArtifacts(); 
Iterator<Artifact> allArtifactsIter = allArtifacts.iterator(); 

while (allArtifactsIter.hasNext()) { 
    Artifact artifact = (Artifact) allArtifactsIter.next(); 
    if (!subsetOfArtifacts.contains(artifact)) { 
     subsetOfArtifacts.add(artifact); 
    } 
} 

我想理想地有一个按级别排列的所有独特工件的列表。我该如何做到这一点?

+0

这将迫使你有独特的水平,以及。最好的解决方案可能是一个明显的,简单的,多步骤的方法,而不是试图将所有这些都集成到一个数据结构中。 –

+0

是否启用断言,同时运行'-ea'开关 –

回答

3

如果您覆盖equals(),则应该覆盖hashCode()!否则,集合的行为,特别是集合,是未定义的。你应该将这个方法添加到您的类:

@Override 
public int hashCode() { 
    return title.hashCode(); 
} 

接下来,你应该使用一个HashSet来代替,而Set sortedSet = new TreeSet(set);的排序。一旦你这样做,它应该都可以正常工作。

的原因是哈希表依赖于一个事实,即如果两个对象equal()那么他们hashCode()相等。下面是从的Javadoc hashCode()

hashCode的一般合同的摘录:

  • 每当它是一个Java应用程序的执行,hashCode方法必须在同一对象不止一次调用一致 返回相同的整数,前提是没有使用等于 的信息在对象上进行比较被修改。该整数不必保持 从应用程序的一次执行到同一应用程序的另一次执行 的一致。
  • 如果两个对象根据equals(Object)方法相等,则对这两个对象中的每一个调用hashCode方法必须产生相同的整数结果 。
  • 如果两个对象根据equals(java.lang.String)是不相等的,则不是必需的。Object)方法,然后调用 上的hashCode方法,每个对象都必须产生不同的整数结果。 但是,程序员应该意识到,为不相等的对象生成不同的 整数结果可能会提高 哈希表的性能。
+2

什么是哈希集?他只会谈论treesets –

+0

是真的。他应该使用HashMap。我将编辑答案 – Bohemian

+1

如果他需要TreeSet,则不需要使用HashSet。 – rob

1

您不仅需要compareTo来比较级别,而且还需要它来比较标题,因为equals会比较标题。

public int compareTo(Artifact aThat) { 

    final int BEFORE = -1; 
    final int EQUAL = 0; 
    final int AFTER = 1; 

    if (this == aThat) return EQUAL; 

    if (this.level < aThat.level) return BEFORE; 
    if (this.level > aThat.level) return AFTER; 
    return this.getTitle().compareTo(aThat.getTitle()); 

//  assert this.equals(aThat) : "compareTo inconsistent with equals."; 

// return EQUAL; 
} 

此外,波希米亚提到,你应该重写hashCode()方法,如果你忽略equals(),但是这不是你的原因是TreeSet中允许您添加重复的项目。

0

RTFM:d 的javadoc TreeSet中明确指出: “请注意,由一组(无论是否提供了明确的比较器)保持的顺序必须与equals一致,如果它是要正确实现设置界面“

您的等于和比较器不一致。你需要添加的那个,然后你将不得不对它进行排序。

您可能需要创建自己的实现为您的使用情况

和其他人说:如果你改变了等号,经常改变的哈希码。

2个相等的对象必须产生相同的散列码。

0

您的compareTo首先应该检查关卡的等级,然后是标题,如果您希望它先按级别排序然后按标题排序,并且只有在关卡和标题相同的情况下才返回平等。类似这样的:

@Override 
public int compareTo(Artifact aThat) 
{ 
    final int BEFORE = -1; 
    final int EQUAL = 0; 
    final int AFTER = 1; 

    if (this == aThat) return EQUAL; 

    if(this.level < aThat.level) return BEFORE; 
    if(this.level > aThat.level) return AFTER; 

    int compare = this.getTitle().compareTo(aThat.getTitle()); 

    if(compare != EQUAL) return compare; 

    assert this.equals(aThat) : "compareTo inconsistent with equals."; 

    return EQUAL; 
} 

在发布之前没有看到rob的回答。