• 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
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    NDK开发一
    【转】Android NDK学习(2)Windows下NDK开发环境配置
    【转】Android NDK学习(3)使用Javah命令生成JNI头文件 .
    IDA 动态调试so
    Scrapy下载中间件的优先级(神踏马值越小优先级越高)
    二、深入asyncio协程(任务对象,协程调用原理,协程并发)
    python 可迭代对象,迭代器,生成器的区别及使用
    一、初识asyncio协程
    python多进程,进程池,数据共享,进程通信,分布式进程
    Scrapy的Request和Response对象
  • 原文地址:https://www.cnblogs.com/moxiaotao/p/10227854.html
Copyright © 2020-2023  润新知