前面的文章,我们系统的介绍了查找算法,排序算法,以及数组和链表各自的表现,较高级的数据结构比如哈希表,二叉树,甚至 优先级队列,堆,等 也做了介绍,那么今天就围绕这些东西,简单明了的根据上述数据结构的特点,来教大家遇到一个需求的时候 怎样选择上述的数据结构(准确的说是和java中的集合框架结合起来)
List如何选择?
我们首先看两张简单的图:
主要根据上述图中所引申到的主要类来做具体阐述。
Vector、ArrayList、LinkedList
Vector:线程安全的动态数组,如果容量满的时候显然要创建新的数组,既然创建新的数组就必然涉及到拷贝数组。 且,由于他是线程安全的,所以你如果没有强烈的同步需求那么可以不要选择他。
ArrayList:本身不是线程安全的,内部数据结构也是数组。也可以调整容量,不过vector一次性扩大一倍,而arrayList 只增加百分之50.
LinkedList:双向链表的数据结构,也是线程不安全的。
有了之前几篇文章的数据结构基础,那么再看这三个的优劣就显而易见了吧(比你之前强背概念要好的多)。
Vector和ArrayList 因为内部是数组结构,所以随机访问元素的性能比较好,但是如果你老是在这些数据的 非尾部 进行数据的增加或者删除,那肯定效率极低,因为我们都知道数组进行类似操作要进行拷贝操作。
反过来LinkedList因为是链表做数据结构,所以你不管在哪个位置进行增加或者删除元素的操作都比前面2者快一些。 但是相应的,他因为是链表所以随机访问元素的性能比较差。
List,Set,Queue 三者具体有啥区别啊?
List 就是前面介绍的,大家最熟悉的基础数据结构。不多说了 Set 下面的东西要特殊一点,他下面的数据结构是不允许有重复数据的,如果我们遇到的需求是要保证元素唯一性的那么就用set 是最合适不过的了。 Queue/Deque: 这个大家平时接触的可能比较少,队列。
注意啊 这三者都是接口,都是interface,具体对应这三者的操作 都被封装在 abstract类中了,比如说abstractList,abstractSet等。
甚至于LinkedList同时是List和Queue
TreeMap和HashMap 啥区别?
实际上treemap内部就是用的平衡二叉搜索树---红黑树来完成的,而hashmap是哈希表,这两者的优劣区别我们前面文章提到过 主要就是红黑树还可以so easy的完成排序,但是哈希表不行。
另外要注意的是有几个马甲别搞混了,treeset里面的主要实现是由treemap来完成的,同样hashset的主要实现也是由hashmap 来完成的。
treeset和treemap啥区别?
其实最主要的区别就是前者是set接口下面的,后面是map接口下面的,treeset是存储对象本身的,treemap还是存储键值对的。 既然是set包下面的所以treeset自然而然也不支持插入重复数据。其实你也可以理解成map下面提供的多数是put操作, 发现key相同的时候,就会主动更新对应的value。而set包下面的提供的都是add操作,如果add的对象 equals方法返回true 那么就直接插入失败了。
hashset,hashmap,hashtable怎么用?
首先,hashset底层是用hashmap来实现的,有兴趣的同学可以翻翻源码,除此之外,这2 没有啥共同点,因为hashset实现的是 set接口,而hashmap实现的是map接口。
hashmap我们都知道存储的是一个个的key-value键值对,而hashset则是仅仅存储对象本身。且hashset因为是set下面的所以 不支持add相同的值。
hashtable实际上可以理解成支持同步的hashmap。但是因为性能问题大家现在都不用了。
LinkedHashMap和treemap都是"有序"的吗?
其实这个问题前面的几篇文章讲清楚了,这里就再稍微重复一遍。LinkedHashMap底层依旧是一个哈希表的结构,只不过呢 除此之外还额外维护了一个双向链表。你每次访问这个hash表的时候呢,比如put,get之类的操作都会触发这个双向链表的 “权重”。简单来说默认的hashmap不支持排序,但是LinkedHashMap则代表 某种程度上支持“排序”。即:
按照进入的顺序进行排序,即先进去的在前面,后进去的在后面
也可以理解成:
使用的次数越多那么就越在前面
而treemap我们都知道底层是红黑树,即平衡二叉搜索树,这个是绝对排序的,绝对到我们需要对treemap存储的数据 实现Comparator 或 Comparable。