TreeSet和TreeMap不能存放重复元素?能不能存放null?

问题一:本来认为TreeMap不能存放重复元素?其实并非如此;
其实一般情况下是不允许存放重复元素的,但是它并非这么死板,在一些情况下是可以存放重复元素的,存了又会有引入其他问题。
问题二:能不能存放null呢?正常情况下是不能的,会报异常,但是经过一些处理后是可以的。
解答问题一:
1、存放元素时,TreeMap实现外部比较器接口Comparator,并重写其compare方法,当判断元素重复时,强制compare方法返回一个非0的数,就可以将重复元素存入;

TreeMap<Integer,String> tree = new TreeMap<Integer,String>(new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
if(o1.equals(o2))
return 1;
else
return o1-o2;
}
});

这种是通过外部比较器进行排序,即是,不通过元素自身的方法来比较,而通过集合实现比较器接口来进行排序。上面代码,通过外部比较器中重写compare方法,判断其返回值来确定排序位置,判断结果有三种:(一)大于0,(二)小于0,(三)等于0;大于0时,表示o1比o2大,因此要排在后面,,小于0时,表示o1比o2小,因此要排在前面,等于0时,集合会认为二者相等,即已经存在此元素了,不再存储(从这一点可以反映出TreeMap集合框架的防止元素重复的机制),但是会对值进行更新(我们的重点不在值)。~~这一点就体现了TreeMap集合的灵活性了,我们如果想存入重复元素,那么就可以控制compare方法的返回值,来达到目的。这样是有效的→→↓↓;
但是???问题来了,比如我们在compare中重写,判断两个元素一样是,强制返回1,元素是存进去了,可是我们在调用get方法去拿出这个元素和其值时,就出问题了,拿到的永远是null,也就是找不到这个元素!不按常规出牌总是要付出代价的,为什么呢??查看底层代码,我们可以发现,get方法取元素同样是根据比较器来取,调用compare方法查找,直到查找到能让compare方法返回0的元素,就判断,这个元素就是我们要找的元素,就将它的值取出来,如果查完了也没有返回0,那么就认为集合中不存在这个键,返回null!
Demo:

TreeMap<Integer,String> tree = new TreeMap<Integer,String>(new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
if(o1.equals(o2))
return 1;
else
return o1-o2;
}
});
tree.put(1, "唐僧");
tree.put(2, "李白");
tree.put(5, "白居易");
tree.put(3, "孙悟空");
tree.put(2, "李黑");
System.out.println(tree);
System.out.println("get(1):"+tree.get(1)+" get(2)"+tree.get(2));

输出:
{1=唐僧, 2=李白, 2=李黑, 3=孙悟空, 5=白居易}
get(1):null get(2)null

将compare方法中的equles判断返回值改为0,输出:
{1=唐僧, 2=李黑, 3=孙悟空, 5=白居易}
get(1):唐僧 get(2)李黑

同样的道理,TreeSet其实就是通过TreeMap来实现的,那么其也响应的特性。

—————————————————————————–
解答问题二:
能不能存放null呢?是可以存放的,但是要避免一个问题,避免出现空指针异常,这个问题是很容易出现的;
如果不实现Comparator接口,那么一定会报出空指针异常(有人会问了,不是还可以用元素实现内部比较器接口吗?是可以实现接口,但是实现了后,存入一个空元素也没法调用它里面的compareTo方法。。),如果实现了Comparator接口,通过适当的写法,时可以避免出现空指针异常,并且顺利的将元素存入和取出:

TreeMap<Integer,String> tree = new TreeMap<Integer,String>(new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
if(o1 !=null&&o2!=null)
return o1-o2;
else if(o1 == null&&o2 != null){
return -1;
}else if(o1!=null&&o2==null)
return 1;
else
return 0;
}
});
tree.put(1, "唐僧");
tree.put(2, "李白");
tree.put(5, "白居易");
tree.put(3, "孙悟空");
tree.put(2, "李黑");
tree.put(null, "赵信");
System.out.println(tree);
System.out.println("get(1):"+tree.get(1)+" get(2)"+tree.get(null));

输出:
{null=赵信, 1=唐僧, 2=李黑, 3=孙悟空, 5=白居易}
get(1):唐僧 get(2)赵信
---------------------
作者:TT海浅
来源:CSDN
原文:https://blog.csdn.net/u010698072/article/details/55255073
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自www.cnblogs.com/moxiaotao/p/10227854.html