复习一下Java中的集合类,是面试笔试中常考察的一个点,特意作的整理。java
集合类,也叫容器类。Java集合类能够用来存储数量庞大的对象。python
咱们和数组进行对比:面试
数组:存储基本数据类型,数据类型单一,长度固定,不能动态添加数据。算法
集合:存储的便可是基本类型的值,也能够是对象,能够存储多种数据类型,长度可变,能够动态添加数据。编程
Java集合类主要有两个接口派生而出:Collection和Map。即集合类都是实现的这两个接口。咱们在实际编程中常用的有 List、Set、Queue(这些是实现的 Collection 接口)HashMap、TreeMap、HashTable(这些实现的 Map 接口)数组
Collection 接口位于 Java.util 包下,是一个父接口, List、Set、Queue 都是实现的 Collection 接口。Collection 作为父接口提供一些操做集合类的方法,所以它的子接口也有这些方法。安全
Collection 接口不能被实例化,而且在实际的编程过程当中几乎不会使用它进行数据的存储。数据结构
Map 接口实现的是键值对的存储,相似 python 中的 dict。框架
Map中比较常见的是 HashMap、TreeMap、Hashtable 类。ide
Set 接口继承自 Collection 接口,Collection 接口有的方法 Set 接口中也有。
Set 接口自身的特性:
Set 接口有两个比较经常使用的具体实现,HashSet、TreeSet。下面分别说一下这两个集合类。
主要特色是快速查找元素。HashSet 是基于 Hash 算法来实现的,在每次添加新的对象的时候,会根据散列码来判断对象是否重复,散列码的获取是经过 Object 的 hashCode() 来实现的。一样 HashSet 也是无序的。
1 import java.util.*; 2 /** 3 * @author jyroy 4 * HashSet使用 5 */ 6 public class HashSetDemo { 7 public static void main(String[] args) { 8 HashSet hashSet = new HashSet(); 9 hashSet.add("Tom"); 10 hashSet.add("Jack"); 11 hashSet.add("Roy"); 12 System.out.println(hashSet); 13 } 14 }
当有重复元素添加时,结果以下
1 import java.util.*; 2 /** 3 * @author jyroy 4 * HashSet使用 5 */ 6 public class HashSetDemo { 7 public static void main(String[] args) { 8 HashSet hashSet = new HashSet(); 9 hashSet.add("Tom"); 10 hashSet.add("Tom"); 11 hashSet.add("Jack"); 12 hashSet.add("Roy"); 13 System.out.println(hashSet); 14 } 15 }
主要特色是会进行天然排序,一样不能重复。参考以下的代码,能够看出 TreeSet 把本来无序的值进行了从新排序,依据的就是天然排序。
1 import java.util.*; 2 public class TreeSetDemo { 3 public static void main(String[] args) { 4 TreeSet treeSet = new TreeSet(); 5 treeSet.add("Tom"); 6 treeSet.add("Jack"); 7 treeSet.add("Roy"); 8 System.out.println(treeSet); 9 } 10 }
然而,在实际开发中不少时候咱们不少时候遵循的不是天然排序,而是有本身定义的排序规则,咱们要作的就是新建一个类而且实现 compareTo() 方法。
下面的代码实现的是根据年龄由小到大进行排序,比较简单,一看就懂的代码。
1 import java.util.TreeSet; 2 class Person implements Comparable{ 3 public String name; 4 public int age; 5 @Override 6 public String toString() { 7 return "Person [name=" + name + ", age=" + age + "]"; 8 } 9 @Override 10 public int compareTo(Object o) { 11 Person person = (Person) o; 12 if(this.age < person.age) { 13 return -1; 14 }else if(this.age > person.age) { 15 return 1; 16 }else { 17 return 0; 18 } 19 } 20 } 21 public class TreeSetDemoCompareto { 22 public static void main(String[] args) { 23 TreeSet treeSet = new TreeSet(); 24 Person person1 = new Person(); 25 Person person2 = new Person(); 26 Person person3 = new Person(); 27 person1.name = "Tom"; 28 person1.age = 20; 29 person2.name = "Jack"; 30 person2.age = 21; 31 person3.name = "Roy"; 32 person3.age = 22; 33 treeSet.add(person1); 34 treeSet.add(person2); 35 treeSet.add(person3); 36 System.out.println(treeSet); 37 } 38 }
List 接口继承了 Collection 接口,Collection 接口有的方法 List 中也有。
List 接口自身的特性:
List 接口有两个比较经常使用的具体实现,ArrayList、Vector、LinkedList。下面分别说一下这两个集合类。
ArrayList 自己是经过数组的方式实现的,大小能够随着对象的增长而增长。查询效率比较高,增长、删除的效率比较低,这也是数组的一种特性。非线程安全的。并且是有序的。
1 import java.util.*; 2 /** 3 * @author jyroy 4 */ 5 public class ArrayListDemo { 6 public static void main(String[] args) { 7 List arrayList = new ArrayList(); 8 arrayList.add("Tom"); 9 arrayList.add("Jack"); 10 arrayList.add("Roy"); 11 System.out.println(arrayList); 12 } 13 }
Vector 和 ArrayList 是类似的,都是经过数组来实现的。
最大的区别就是线程安全方面。Vector 是线程安全的,同步的,Vector类对集合的元素操做时都加了synchronized,保证线程安全。而 ArrayList 是非线程安全的。也是由于线程安全的问题,ArrayList 的查询效率比 Vector 要高。
另一个区别是在扩容方面,Vector默认扩容是增加一倍的容量,Arraylist是增加50%+1的容量。
Vector与ArrayList的remove,add(index,obj)方法都会致使内部数组进行数据拷贝的操做,这样在大数据量时,可能会影响效率。
1 import java.util.*; 2 public class VectorDemo { 3 public static void main(String[] args) { 4 List vectorList = new Vector(); 5 vectorList.add("Roy"); 6 vectorList.add("Tom"); 7 vectorList.add("Jack"); 8 System.out.println(vectorList); 9 } 10 }
LinkedList 和 ArrayList、Vector相比,在方法的使用上都是类似的。
LinkedList 是基于双向链表的,比较利于对象的增长和删除操做,可是对查询的支持不够好,这是链表的特色。 LinkedList 一样是线程不安全的。
1 import java.util.*; 2 public class LinkedListDemo { 3 public static void main(String[] args) { 4 List linkedList = new LinkedList(); 5 linkedList.add("Roy"); 6 linkedList.add("Jack"); 7 linkedList.remove(0); 8 linkedList.add("Tom"); 9 System.out.println(linkedList); 10 } 11 }
Queue 是 Collection 的子接口,中文称为队列,特性就是先进先出,先进入队列的对象,在进行删除的时候最早被删除。全部的删除操做都是在队首进行的,全部的插入操做都是在队尾进行的。
1 import java.util.*; 2 public class QueueDemo { 3 public static void main(String[] args) { 4 Queue queue = new LinkedList(); 5 queue.add("Tom"); 6 queue.add("Roy"); 7 System.out.println(queue.poll()); //出队列操做 8 queue.add("Jack"); 9 System.out.println(queue); 10 } 11 }
HashMap 是基于散列表的 Map 接口的实现类,线程不安全。
散列表是经过关键码值(Key value)而直接进行访问的数据结构。它经过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。
下面的代码实现了获取key为 2 的元素的 value。
1 import java.util.*; 2 public class HashMapDemo { 3 public static void main(String[] args) { 4 HashMap hashMap = new HashMap(); 5 hashMap.put(1, "Tom"); 6 hashMap.put(2, "Jack"); 7 hashMap.put(3, "Roy"); 8 System.out.println(hashMap.get(2)); 9 System.out.println(hashMap); 10 } 11 }
TreeMap 是根据红黑树算法实现的,TreeMap最大的特性就是支持天然排序。从下面的代码中也能够很是清晰的看出 TreeMap 利用 key 值进行了天然排序。
红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。
1 import java.util.*; 2 public class TreeMapDemo { 3 public static void main(String[] args) { 4 TreeMap treeMap = new TreeMap(); 5 treeMap.put("2", "Tom"); 6 treeMap.put("1", "Roy"); 7 treeMap.put("3", "Jack"); 8 System.out.println(treeMap); 9 } 10 }
HashTable 和 HashMap 是基本一致的。
最大的区别是 HashTable 是线程安全的,HashMap 不是。
1 import java.util.*; 2 public class HashTableDemo { 3 public static void main(String[] args) { 4 Hashtable hashtable = new Hashtable(); 5 hashtable.put("2", "Tom"); 6 hashtable.put("1", "Roy"); 7 hashtable.put("3", "Jack"); 8 System.out.println(hashtable); 9 } 10 }
这些问题是在其余一些大佬的博客中看到,作了一个整理,都是 Java 集合类的问题。
1. ArrayList和LinkedList的特色和区别?
ArrayList: 底层用数组实现,因为数组能够经过下标直接访问指定索引的元素,所以,ArrayList经过索引查询元素很是快。但因为插入和删除元素时都会进行数组的从新排列,所以,ArrayList的插入和删除操做比较慢。
LinkedList:底层用链表实现,因为链表没有具体的下标,所以,访问某个索引的节点时须要遍历该节点前面的全部元素,速度比较慢。因为插入和删除元素时只须要更新相应元素的指针(或引用),不用从新排列元素,所以,LinkedList对插入和删除操做比较快。
LinkedList 比 ArrayList消耗更多的内存,由于 LinkedList 中的每一个节点存储了先后节点的引用。
2. ArrayList和Vector的区别?
ArrayList非线程安全,Vector线程安全。在扩容时,ArrayList默认扩容当前容量的50%,但Vector默认扩容当前容量的100%。
3. HashSet和TreeSet的区别?
HashSet基于HashMap,用键来存放HashSet的值,因为HashMap的键不能重复,所以,HashSet的值也不会重复,这是集合的一个特色。
TreeSet基于TreeMap,也是用键来存放TreeSet的值。TreeMap的底层实现是红黑树,其根据键排序,能够获得排好序的数据。
4. HashMap和HashTable的区别?
HashMap非线程安全,HashTable线程安全。
HashMap能够容许一个null键和多个null值,但HashTable不容许,会出现NullPointerException。
5. HashMap和TreeMap的区别?
HashMap中存放的键是随机的,具备较快的访问和存取速度,TreeMap中的键是按照天然排序排好的。
6. Java集合框架的基础接口有哪些?
Collection 和 Map ,一个元素集合,一个是键值对集合; 其中 List、Set、Queue 接口继承了 Collection 接口,一个是有序元素集合,一个是无序元素集合,一个是队列; 而 ArrayList 和 LinkedList 实现了 List 接口,HashSet 实现了 Set 接口,这几个都比较经常使用; HashMap、HashTable、TreeMap 实现了 Map 接口,而且 HashTable 是线程安全的,HashMap 是非线程安全的,可是 HashMap 性能更好。
7. 如何决定选用HashMap仍是TreeMap?
8. 哪些集合类提供对元素的随机访问?
ArrayList、HashMap、TreeMap和HashTable类提供对元素的随机访问。
9. Array和ArrayList有何区别?何时更适合用Array?
Array能够容纳基本类型和对象,而ArrayList只能容纳对象。
Array是指定大小的,而ArrayList大小是根据内容自动扩张的。
Array没有提供ArrayList那么多功能,好比addAll、removeAll和iterator等。尽管ArrayList明显是更好的选择,但也有些时候Array比较好用。
(1)若是列表的大小已经指定,大部分状况下是存储和遍历它们。
(2)对于遍历基本数据类型,尽管Collections使用自动装箱来减轻编码任务,在指定大小的基本类型的列表上工做也会变得很慢。
(3)若是你要使用多维数组,使用[][]比List<List<>>更容易。