问题描述:对已有的set集合进行排序:Set中保存的对象,按照对象的某个属性进行排序。
例如,set中保存的Model如下:
package test.collection;
/**
* Created by on 2015/10/10.
*/
public class Model {
private String key;
private Man man;
private WoMan woMan;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Man getMan() {
return man;
}
public void setMan(Man man) {
this.man = man;
}
public WoMan getWoMan() {
return woMan;
}
public void setWoMan(WoMan woMan) {
this.woMan = woMan;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Model model = (Model) o;
if (!key.equals(model.key)) return false;
if (man != null ? !man.equals(model.man) : model.man != null) return false;
return !(woMan != null ? !woMan.equals(model.woMan) : model.woMan != null);
}
@Override
public int hashCode() {
int result = key.hashCode();
result = 31 * result + (man != null ? man.hashCode() : 0);
result = 31 * result + (woMan != null ? woMan.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Model{" +
"key='" + key + '\'' +
", man=" + man +
", woMan=" + woMan +
'}';
}
}
Man 和Woman对象分别如下所示:
Man对象:
package test.collection;
/**
* Created by 2015/10/10.
*/
public class Man {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
Woman对象:
package test.collection;
/**
* Created by on 2015/10/10.
*/
public class WoMan {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
第一次使用的方式如下代码所示,该代码会将排序属性相同的对象覆盖:
package test.collection;
import com.google.common.collect.Sets;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
/**
* Created by on 2015/10/10.
*/
public class TreeSetTest {
public static void main(String[] args) {
Man man = new Man();
man.setAge(15);
man.setName("yrq");
WoMan woMan = new WoMan();
woMan.setAge(17);
woMan.setName("wp");
Model firstModel = new Model();
firstModel.setKey("hello");
firstModel.setMan(man);
Model secondModel = new Model();
secondModel.setKey("hello");
secondModel.setWoMan(woMan);
// 将两个model对象放入到set中
Set<Model> models = Sets.newHashSet(firstModel, secondModel);
// 打印初始化的set大小, 此时为2
System.out.println(models.size());
// 定义比较器
Comparator<Model> comparator = new Comparator<Model>() {
@Override
public int compare(Model o1, Model o2) {
return o1.getKey().compareTo(o2.getKey());
}
};
TreeSet<Model> sortModels = new TreeSet<Model>(comparator);
// 将原来的set添加到有序的set中
sortModels.addAll(models);
// 打印此时的有序的set大小,此时大小为1,只有firstModel存在该set中
System.out.println(sortModels.size());
}
}
然后修改了第一次的代码如下,将set转化为list,得到排序的list,同样可以得到结果, 代码如下:
package test.collection;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.*;
/**
* Created by on 2015/10/10.
*/
public class TreeSetTest {
public static void main(String[] args) {
Man man = new Man();
man.setAge(15);
man.setName("yrq");
WoMan woMan = new WoMan();
woMan.setAge(17);
woMan.setName("wp");
Model firstModel = new Model();
firstModel.setKey("hello");
firstModel.setMan(man);
Model secondModel = new Model();
secondModel.setKey("hello");
secondModel.setWoMan(woMan);
// 将两个model对象放入到set中
Set<Model> models = Sets.newHashSet(firstModel, secondModel);
// 打印初始化的set大小, 此时为2
System.out.println(models.size());
// 定义比较器
Comparator<Model> comparator = new Comparator<Model>() {
@Override
public int compare(Model o1, Model o2) {
return o1.getKey().compareTo(o2.getKey());
}
};
ArrayList<Model> modelArrayList = Lists.newArrayList(models);
Collections.sort(modelArrayList, comparator);
System.out.println(modelArrayList);
}
}
之所以写了第一种方式,是因为果断认为set中放入对象是根据equals方法和hashcode来判断的,然而在treeSet的实现中,是基于treeMap的实现的,例如treeSet的代码的add方法其实是调用的treeMap的如下方法:
//treeSet的add方法原型如下:
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
// 然后treeMap的put方法如下:
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
// 以上put方法的关键代码如下:
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
// 由此可知,compareTo的结果相等时,更新原来的值,而不是把对象放入
(adsbygoogle = window.adsbygoogle || []).push({});