简体   繁体   English

Java设置奇怪的行为

[英]Java Set strange behaviour

I had a problem in which I need to change the comparable value of a sorted set based on some condition. 我有一个问题,需要根据某些条件更改排序集的可比值。

Doing something like this: 做这样的事情:

SortedSet<T> groups;

for(T t: groups){
        t.setOrdinal(max);
}

Will not automatically rearrange the SortedSet. 不会自动重新排列SortedSet。

Reading online I figured out that I need to remove the object from the set and then add it again. 在线阅读我发现我需要从集合中删除该对象,然后再次添加它。 Obviously, I cannot do it while iterating over the set. 显然,在遍历集合时我无法做到这一点。 So I decided to make a Arraylist of the set. 因此,我决定制作一组Arraylist。 Make the set null and then add all the elements again so that they follow the sorted order. 将集合设为null,然后再次添加所有元素,以使它们遵循排序的顺序。 I did something like this: 我做了这样的事情:

SortedSet groups; SortedSet组;

List<T> groupList = new ArrayList<T>(groups);
groups = null;
for(T t: groupList){
        t.setOrdinal(max);
}

groups = new TreeSet<T>(groupList);

But when I check the groups set it didnt follow the sort order based on comparator which compared the ordinal of the object T 但是当我检查组设置时,它没有遵循基于比较器的排序顺序,比较器比较了对象T的序数

But when I tried something like this: 但是当我尝试这样的事情时:

SortedSet groups; SortedSet组;

List<T> groupList = new ArrayList<T>(groups);
groups.clear();
for(T t: groupList){
        t.setOrdinal(max);
}

groups.addAll(groupList);

I got the result as expected. 我得到了预期的结果。 Can someone explain me whats happening? 有人可以解释我发生了什么事吗?

This is how I have implemented my class T 这就是我实施班级T的方式

public class T implements Serializable, Comparable<T> {
//
int ordinal;
//getter
//setter

 @Override
  public int compareTo(T that) {
    if (that == null) {
      return 1;
    }

    return this.ordinal - that.ordinal;
  }

}

For those want to see complete program: 对于那些想看完整程序的人:

List<SmartUser> groupsList = new ArrayList<SmartUser>(groups);
groups = null;
for (SmartUser smartUser : groupsList) {
        if (smartUser.isExpired()) {
                smartUser.setOrdinal(Long.MAX_VALUE);
        }
        SmartUserQuery smartUserQuery = smartUser.getSmartUserQuery();
        if (smartUserQuery != null) {
                //Do parallel processing: of each samrtUser
        }
}

groups = new TreeSet<SmartUser>groupsList;

Correct result giving approach: 正确的结果给出方法:

List<SmartUser> groupsList = new ArrayList<SmartUser>(groups);
groups.clear();
for (SmartUser smartUser : groupsList) {
        if (smartUser.isExpired()) {
                smartUser.setOrdinal(Long.MAX_VALUE);
        }
        SmartUserQuery smartUserQuery = smartUser.getSmartUserQuery();
        if (smartUserQuery != null) {
                //Do parallel processing: of each samrtUser
        }
}

groups.addAll(groupsList);

Thanks. 谢谢。

Change your compareTo method to below 将您的compareTo方法更改为下面

@Override
public int compareTo(CustomObject o) {
    return Integer.valueOf(o.ordinal).compareTo(ordinal );
}

Also as per TreeSet contract you should provide equals method which will be in sync with compareTo method 此外,根据TreeSet合同,您应提供equals方法,该方法将与compareTo方法同步

 @Override
public boolean equals(Object obj) {
    if (obj == null)
        return false;
    if (!(obj instanceof CustomObject))
        return false;
    CustomObject o = (CustomObject) obj;

    return this.ordinal == o.ordinal;
}

A Sample implementation 样例实现

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class CustomObject implements Comparable<CustomObject> {

private int ordinal = 0;

public CustomObject(int priority) {
    this.ordinal = priority;
}

/**
 * @param args
 */
public static void main(String[] args) {

    List<CustomObject> list = new ArrayList<CustomObject>();
    list.add(new CustomObject(1));
    list.add(new CustomObject(2));
    list.add(new CustomObject(3));
    list.add(new CustomObject(6));
    list.add(new CustomObject(4));
    System.out.println("Before: " + list);
    for (CustomObject object : list) {
        if (object.ordinal == 4) {
            object.ordinal = 10;
        }
    }
    Set<CustomObject> set = new TreeSet<CustomObject>();
    set.addAll(list);
    System.out.println("After: " + set);

}

@Override
public int compareTo(CustomObject o) {
    return Integer.valueOf(o.ordinal).compareTo(ordinal);
}

@Override
public boolean equals(Object obj) {
    if (obj == null)
        return false;
    if (!(obj instanceof CustomObject))
        return false;
    CustomObject o = (CustomObject) obj;

    return this.ordinal == o.ordinal;
}

@Override
public String toString() {
    return " Ordinal Value is :" + ordinal;
}

}

I figured out that I need to remove the object from the set and then add it again. 我发现需要从集合中删除该对象,然后再次添加它。 Obviously, I cannot do it while iterating over the set. 显然,在遍历集合时我无法做到这一点。 So I decided to make a Arraylist of the set. 因此,我决定制作一组Arraylist。

Take a look at my answer at maintaining TreeSet sort as object changes value and try my UpdateableTreeSet implementation. 看一下我在对象更改值维护TreeSet排序的答案,并尝试执行UpdateableTreeSet实现。 It permits you to do deferred updates while iterating over the sorted set. 它允许您在迭代排序后的集合时进行延迟更新。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM