一.集合的继承体系
二.集合与数组的区别
数组:数组长度固定;数组是相同数据类型的集合;数组既可以存放基本数据类型,也可以存放引用数据类型。
集合:集合数组长度不固定;集合可以存放不同数据类型的数;集合只能存放引用数据类型。
三.Collection的继承接口与实现类
1.概述
Collection是集合的最顶层,他是一个接口,List与Set继承于他。
List集合存放的都是有序(有序是指存放有序,并不是会在集合中进行排序),数据可重复,这是和Set集合最大的区别。
Set集合存放的数据无序(存入和取出的顺序不一定一致)并且数据不可重复
2.List的实现类
List有三个实现类,分别为ArrayList,Vector,LinkedList.
ArrayList:底层是数组,查询快,删除慢,是一个线程不安全的集合。
Vector:底层是数组,查询快,删除慢,是一个线程安全的集合.
LinkedList:底层是链表,查询慢,删除快,是一个线程不安全的集合。
3.Set的实现类
Set有两个实现类,HashSet和TreeSet
HashSet:底层是哈希表,是一个不同步,线程不安全的集合。
TreeSet:底层是红黑树,是一个不同步,线程不安全的集合。他会自动对放入的数进行排序,所以放入的数需要可以排序,不然会报ClassCastExpection。
对于Treeset的排序有两种:
1.自然排序:需要实现comparable接口,重写compare方法
public class Student implements Comparable<Student>{ private String name; private int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } //自然排序 @Override public int compareTo(Student o) { int num1=this.age-o.age; int num2=(num1==0)?this.name.compareTo(o.name):num1; return num2; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } }
public class TreeSetDemo { public static void main(String[] args) { // 按年龄将学生排序,如果年龄相同就按名字排序 TreeSet<Student> ts = new TreeSet<>(); Student s1 = new Student("张三", 22); Student s2 = new Student("李四", 19); Student s3 = new Student("王五", 18); Student s4 = new Student("赵六", 20); Student s5 = new Student("张飞", 22); Student s6 = new Student("关羽", 18); ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); ts.add(s5); ts.add(s6); Iterator<Student> iterator = ts.iterator(); while (iterator.hasNext()) { Student student = (Student) iterator.next(); System.out.println(student); } } }
2.比较器排序:要实现comparator接口,重写compare方法
public class Student { private String name; private int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } }
public class TreeSetDemo2 { public static void main(String[] args) { // 按年龄将学生排序,如果年龄相同就按名字排序 TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() { //比较器排序 @Override public int compare(Student o1, Student o2) { int num1=o1.getAge()-o2.getAge(); int num2=(num1==0)?o1.getName().compareTo(o2.getName()):num1; return num2; } }); Student s1 = new Student("张三", 22); Student s2 = new Student("李四", 19); Student s3 = new Student("王五", 18); Student s4 = new Student("赵六", 20); Student s5 = new Student("张飞", 22); Student s6 = new Student("关羽", 18); ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); ts.add(s5); ts.add(s6); Iterator<Student> iterator = ts.iterator(); while (iterator.hasNext()) { Student student = (Student) iterator.next(); System.out.println(student); } } }
四.Map
1.Map与Collection的区别
(1)Map与Collection没有关系,两个都是各自集合的最顶层。
(2)Map是以键值对存入的,是双列的,而Collection是单列加入的。
(3)Map的key唯一,Collection的Set是唯一的
(4)Map的数据结构作用于key,而Collection的数据结构作用于元素。
2.Map集合的两个子类
(1)HashMap:底层是一个哈希表,不同步,线程不安全,键唯一,允许null键和null值。
(2)TreeMap:底层是一个红黑树,不同步,线程不安全,key具有唯一性且会排序(放入的数能够排序的,否则要实现comparaable接口或实现comparator接口)
3.Map集合的遍历
(1)利用Map的KeySet取得Set集合,然后对Set集合遍历,通过key值取得value
public static void main(String[] args) { Map<String, String> m = new HashMap<>(); m.put("小李广", "花荣"); m.put("及时雨", "宋江"); m.put("黑旋风", "李逵"); m.put("智多星", "吴用"); Set<String> keySet = m.keySet(); for (String s : keySet) { System.out.println(s + "==" + m.get(s));// 通过key值取得value } }
(2)利用entrySet,取得集合,分别获取Key和value
public static void main(String[] args) { Map<String, String> m = new HashMap<>(); m.put("小李广", "花荣"); m.put("及时雨", "宋江"); m.put("黑旋风", "李逵"); m.put("智多星", "吴用"); Set<Entry<String, String>> set = m.entrySet(); for(Entry<String,String> e:set) { System.out.println(e.getKey()+"=="+e.getValue()); } }
五.collections类阐述
1.集合的工具类,包含对集合的多种操作的静态方法
2.与collection的区别
Collection是集合的最顶层接口,Collections是集合的工具类
3.Collections常用方法
(1)排序:sort()
public static void main(String[] args) { ArrayList <Integer>list=new ArrayList<>(); list.add(1); list.add(4); list.add(3); list.add(8); list.add(2); //for (Integer i: list) { // System.out.println(i); //} Collections.sort(list); for (Integer i: list) { System.out.println(i); } }
(2)二分查找法:binarySearch()(前提:集合是有序的)
public static void main(String[] args) { ArrayList <Integer>list=new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); int a = Collections.binarySearch(list, 3); System.out.println(a);//打印3的下标 }
(3)最大值,最小值:max(),min()
public static void main(String[] args) { ArrayList <Integer>list=new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); int a = Collections.max(list); int b = Collections.min(list); System.out.println(a+" "+b); }
(4)数据反转:reverse()
public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); Collections.reverse(list); for (Integer integer : list) { System.out.println(integer); } }
(5)随机置换:shuffle()(用于扑克)
public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); Collections.shuffle(list); for (Integer integer : list) { System.out.println(integer); } }
六.常见面试题
1.HashMap和Hashtable的区别。
(1)HashMap是线程不安全的集合,而Hashtable使用了Synchronized关键字,是线程安全的集合。
(2)HashMap允许null值和null键,而Hashtable不允许null值和null键。
(3)HashMap有快速失败机制,而HashTable没有。
注:快速失败机制:一个软件或系统面对可能发生的错误的应对机制。
(4)HashMap继承自AbstractMap类,而Hashtable基于陈旧的Dictionary类。
(5)HashTable中hash数组默认大小是11,增加的方式是 old*2+1。
HashMap中hash数组的默认大小是16,而且一定是2的指数。
总结:有多个线程访问相同实例的可能时,就应该使用Hashtable,反之使用HashMap。非线程安全的数据结构能带来更好的性能。
如果在将来有一种可能—你需要按顺序获得键值对的方案时,HashMap是一个很好的选择,因为有HashMap的一个子类 LinkedHashMap。所以如果你想可预测的按顺序迭代(默认按插入的顺 序),你可以很方便用LinkedHashMap替换HashMap。反观要是使用的Hashtable就没那么简单了。同时如果有多个线程访问HashMap,Collections.synchronizedMap()可以代替,总的来说 HashMap更灵活。
2.HahMap怎么解决哈希冲突
(1)通过链地址法(使用散列表)来链接拥有相同hash值的数据。
(2)使用2次扰动函数(hash函数)来降低哈希冲突的概率,使数据分布更加均匀。
(3)jdk1.8引入了红黑树进一步降低了遍历的复杂度,使遍历更快。
3.ArrayList和vector的区别
共同点:
ArrayList和Vector都实现了List接口,顶层都是collection,两个底层都是数组,数据都允许重复
区别:
(1)ArrayList是线程不安全的集合,而vector加了synchronized关键字,是线程安全的集合。如果只有一个线程访问集合,选择ArrayList,效率高;若有多个线程访问集合,选择vector,比较安全。
(2)数据增长:vector是数据满时,增长为原来的两倍,而ArrayList是数据存到一半时,便增长原容量的(0.5倍+1)个空间。