集合与数组
首先我们先来看概念
数组:用来存放对象的一种容器(可以存储基本数据类型),长度固定,不适合对象数量未知的情况下使用。
集合:可以存放多种对象类型的容器(只能存储对象),长度可变。
数组与集合的区别
1、数组声明了数据类型,然后就只能存储那一种数据类型。集合能存放多种(不加泛型时,类型是Object)。
2、数组是静态的,一个数组实例具有固定的大小,一旦创建了就无法改变容量了。集合是动态扩展容量的,可以根据需要动态改变大小。
3、数组是java语言中内置的数据类型,是线性排列的,执行效率或类型检查都是最快的。
集合只能存放对象,基本数据类型如何解决?
可以通过包装类把基本数据类型转为对象类型,存放引用。因为有了自动装箱和自动拆箱功能,想把数据类型存入集合,直接存就可以了。系统会自动将其装箱成封装类,然后放入集合。(未指定泛型的话,集合中拿出来的都是Object类型)
所以用数组的原因是数组比集合快吗?用集合的原因是能存放多种类型对象?
一般用 ArrayList 比较多,它基于数组,又实现了Collection和List接口。可以说是综合了这两个。
集合类体系
单列集合
Collection
├List (有序集合,允许相同元素和null)
│├LinkedList (非同步(线程不安全),允许相同元素和null,增删快查改慢)
│├ArrayList (非同步(线程不安全),允许相同元素和null,实现了动态大小的数组,增删慢查改快)
│└Vector(同步(线程安全),允许相同元素和null,效率低)
│ └Stack(继承自Vector,实现一个后进先出的堆栈)
└Set (无序集合,不允许相同元素,最多有一个null元素)
|-HashSet(无序集合,不允许相同元素,最多有一个null元素)
双列集合
Map (没有实现collection接口,key不能重复,value可以重复,一个key映射一个value)
├Hashtable (实现Map接口,同步(线程安全),不允许null作为key和value,用自定义的类当作key的话要复写hashCode和equals方法,)
├HashMap (实现Map接口,非同步(线程不安全),允许null作为key和value,用的多)
└WeakHashMap(实现Map接口)
Collection接口是集合类的根接口,Java中没有提供这个接口的直接的实现类。但是却让其被继承产生了两个接口,就是Set和List。Set中不能包含重复的元素。List是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式。
Map是Java.util包中的另一个接口,它和Collection接口没有关系,是相互独立的,但是都属于集合类的一部分。Map包含了key-value对。Map不能包含重复的key,但是可以包含相同的value。
Iterator,所有的集合类,都实现了Iterator接口,这是一个用于遍历集合中元素的接口。(使用 for / foreach 循环遍历的时候不能删除集合元素)
主要包含以下三种方法:
①.hasNext()是否还有下一个元素。
②.next()返回下一个元素。
③.remove()删除当前元素。
Iterator 和 ListIterator 的区别是什么?
Iterator 可以用来遍历 Set 和 List 集合,但是ListIterator 只能遍历 List 。
Iterator 对集合只能是前向遍历,ListIterator 可以前向也可以后向。
ListIterator 实现了 Iterator 接口。并且扩展了其他功能(如:增加元素,替换元素,获取前一个后一个元素索引等)
Enumeration 接口和 Iterator 接口的区别有哪些?
Enumeration 速度是 Iterator 的两倍。Iterator 线程安全,可以删除集合元素。
1、List(有序、可重复)
List里存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。
ArrayList和LinkedList的区别
LinkedList经常用在增删操作较多而查询操作很少的情况下,ArrayList则相反。
LinkedList是链表结构,查询的时候是移动指针一个个找过去的,比较慢;而增加只需要连接上去就可以了。
ArrayList是数组结构,查询是根据索引随机查询的,比价快;而增删需要更新索引,所以比较慢。
若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。
2、Set(无序、不能重复)
Set里存放的对象是无序,不能重复的,集合中的对象不按特定的方式排序,只是简单地把对象加入集合中。
set是如何不能加入重复值的?
set 的 add() 方法底层是 map.put(key,value) 方法,我们添加进来的对象放在 map 中 key 的位置
而 map 的 key 是不能重复的。这里靠的是重写了 hashCode() 和 equals() 方法。
TreeSet和HashSet的区别?
首先两者值都不能重复。
TreeSet是二叉树结构的,是自动排好序的,不允许放入null值。
HashSet 的话,是无序的,并且要求放入的对象必须实现HashCode()方法。只能有一个 null 值(这里是map底层判断传入对象是否为空,为空则创建一个为 null 的对象)
3、Map(键值对、键唯一、值不唯一)
Map集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对map集合遍历时先得到键的set集合,对set集合进行遍历,得到相应的值。
HashTable与HashMap
同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的。
HashMap允许存在一个为null的key,多个为null的value 。
hashtable的key和value都不允许为null。
最后我们再重点讲一下 ArrayList
它其实就是动态数组,提供了动态的增加和减少元素
实现了Collection和List接口,可以灵活的设置数组的大小。
线程不安全,因此一般建议在单线程中使用ArrayList。