Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
按一个值对java对象集合进行排序,并按另一个值保持唯一_Java_Collections_Arraylist_Comparator_Treeset - Fatal编程技术网

按一个值对java对象集合进行排序,并按另一个值保持唯一

按一个值对java对象集合进行排序,并按另一个值保持唯一,java,collections,arraylist,comparator,treeset,Java,Collections,Arraylist,Comparator,Treeset,我需要按整数值“level”对java对象集合进行排序。我还需要确定此集合是否已包含按“title”排序的对象 我相信一个集合的最佳选择是一个树集,它拥有一组有序的唯一值 我有一个具有“level”和“title”属性的对象。它实现了如下类似的功能: 它覆盖Equals方法(用于检查对象是否已包含在树集中的“title”中) 代码如下所示: @Override public boolean equals(Object arg0) { Artifact obj = (Artifact)

我需要按整数值“level”对java对象集合进行排序。我还需要确定此集合是否已包含按“title”排序的对象

我相信一个集合的最佳选择是一个树集,它拥有一组有序的唯一值

我有一个具有“level”和“title”属性的对象。它实现了如下类似的功能:

它覆盖Equals方法(用于检查对象是否已包含在树集中的“title”中)

代码如下所示:

@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;
}
@覆盖
公共布尔等于(对象arg0){
工件obj=(工件)arg0;
如果(this.getTitle().equals(obj.getTitle()){
返回true;
}
返回false;
}
@凌驾
公共int比较(工件aThat){
之前的最终整数=-1;
最终整数等于0;
之后的最终整数=1;
如果(this==aThat)返回相等值;
如果(本级<本级)在之前返回;
如果(this.level>aThat.level)在之后返回;
断言此。等于(aThat):“与等于不一致。”;
回报相等;
}
当我尝试从可能具有重复值的arraylist向列表中添加值时。contains似乎不起作用,不管怎样,对象都会添加到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);
    }
 }
TreeSet subsetOfArtifacts=newtreeset();
ArrayList allArtifacts=getArtifacts();
迭代器allArtifactsIter=allArtifacts.Iterator();
while(allArtifactsIter.hasNext()){
工件工件=(工件)allArtifactsIter.next();
如果(!subsetOfArtifacts.contains(artifact)){
添加(工件);
}
}

理想情况下,我希望有一个按级别排序的所有唯一工件的列表。我如何做到这一点?

不仅需要compare来比较级别,还需要它来比较标题,因为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;
}
public int compareTo(工件aThat){
之前的最终整数=-1;
最终整数等于0;
之后的最终整数=1;
如果(this==aThat)返回相等值;
如果(本级<本级)在之前返回;
如果(this.level>aThat.level)在之后返回;
返回这个.getTitle().compareTo(aThat.getTitle());
//断言此。等于(aThat):“与等于不一致。”;
//回报相等;
}
此外,正如Bohemian提到的,如果覆盖equals(),则应覆盖hashCode(),但这不是树集允许添加重复项的原因。

如果覆盖,则也应覆盖!否则,集合(尤其是集合)的行为未定义。应将此方法添加到类中:

@Override
public int hashCode() {
    return title.hashCode();
}
接下来,您应该使用HashSet,并使用
Set-sortedSet=new-TreeSet(Set);
进行排序。一旦您这样做,它应该可以正常工作

原因是哈希表依赖于这样一个事实:如果两个对象是
equal()
,那么它们的
hashCode()
也是相等的

hashCode的总合同为:

  • 每当在Java应用程序的执行过程中对同一对象多次调用hashCode时,hashCode方法必须一致 如果在equals中未使用任何信息,则返回相同的整数 已修改对象上的比较。不需要保留此整数 从应用程序的一次执行到另一次执行的一致性 同样的应用
  • 如果根据equals(Object)方法,两个对象相等,则必须对这两个对象中的每一个调用hashCode方法 生成相同的整数结果
  • 根据equals(java.lang.Object)方法,如果两个对象不相等,则不需要调用 这两个对象中的每一个都必须产生不同的整数结果。 但是,程序员应该知道,生成不同的 不相等对象的整数结果可能会提高 哈希表
RTFM:D javadoc for TreeSet明确指出: “请注意,如果要正确实现set接口,set维护的顺序(无论是否提供显式比较器)必须与equals一致”

你的equals和comparator不一致。你需要添加一个,然后你必须对它进行排序

您可能需要为您的用例创建自己的实现

正如其他人所说:如果你改变了等式,总是改变hashcode


2个相等的对象必须生成相等的哈希代码。

比较器应首先检查级别,然后检查标题,如果您希望它先按级别再按标题排序,并且仅当级别和标题都相等时才返回相等。类似于以下内容:

@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;
}
@覆盖
公共int比较(工件aThat)
{
之前的最终整数=-1;
最终整数等于0;
之后的最终整数=1;
如果(this==aThat)返回相等值;
如果(this.levelaThat.level)在之后返回;
int compare=this.getTitle().compareTo(aThat.getTitle());
如果(比较!=相等)返回比较;
断言此。等于(aThat):“与等于不一致。”;
回报相等;
}

在发布之前,我没有看到rob的答案。

这也将迫使您拥有唯一的级别。最好的解决方案可能是一种显而易见的、简单的、多步骤的方法,而不是试图将所有这些都放在一个数据结构中。您在运行
-ea
switchwhat hashset时启用了断言吗?他只谈到treesetsIt i如果他想要树集,就不必使用哈希集。