TreeSet和TreeMap不能存放重复元素?能不能存放null?其实不是这样的——灵活的二叉树...

TreeSet和TreeMap不能存放重复元素?能不能存放null?其实不是这样的——灵活的二叉树

本文链接: https://blog.csdn.net/u010698072/article/details/55255073

问题一:本来认为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)赵信

 

转载于:https://www.cnblogs.com/it-tsz/p/11508041.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值