目录
集合存储的内容
集合本身是对象,集合中存储的不是基本数据类型,也不是对象,而是对象的引用,即地址。如下图:
不同集合对应不同的数据结构
ArrayList类创建的集合,底层是数组。
LinkedList类创建的集合,底层是链表。
TreeSet类创建的集合,底层是二叉树。
集合继承结构图
list集合存储元素的特点:有序(指放进去的顺序,不是大小顺序)可重复,存储的元素有下标,下标从0开始
set集合的特点:无序(指存进去是这个顺序,取出来是另外的顺序)不可重复,set集合元素没有下标。
集合常用方法
1、boolean add(Object e)方法,集合中不能存储基本数据类型和引用数据类型,add(1)会把1自动装箱,把1变为Integer类型。放进去的是数字1的地址。
2、int size()方法,获取集合中元素的个数。
3、void clear()方法,清空集中的元素。
4、boolean contain(Object e)方法,用于判断集合中是否包含某个元素
5、boolean remove(Object e)方法,用于移除指定元素。
6、boolean isEmpty()方法,判断集合是否为空。
集合的迭代(以下迭代方法在Map集合中不能用)
方法:
1、创建迭代器对象:Iterator it=c.iterator();(c是集合对象)
2、使用两个方法:it.hasNext();it.next();
迭代器的初始位置为-1;即集合中第一个元素的前面
其中,it.hasNext();判断下一个位置是否有元素,有则返回true,否则返回false
其次,it.next();是迭代器往后移动一位,并返回该元素对应的对象(该方法返回的对象是Object对象,若要使用返回对象的方法,需要进行类型强制装换,除非集合在创建时使用了泛型机制,指定集合存储某个类型的元素,这样就会返回指定的对象类型)。
因此,可以使用while循环进行迭代输出,代码如下:
public static void main(String[] args) {
Collection c=new ArrayList();
c.add(1);
c.add(true);
c.add(new Object());
c.add(1.1);
//集合的迭代
Iterator it=c.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
集合迭代器注意事项
1、集合结构发生改变,如添加或删除元素,迭代器就要重新获取,否则会出现异常。如:
(出现异常)
2、在集合元素遍历过程中,不能调用remove方法,否则会出异常。以下代码会出异常:
如果想在迭代过程中删除元素,要用迭代器对象去删,这样集合会同步改变元素,代码如下:
public static void main(String[] args) {
Collection c=new ArrayList();
c.add(1);
c.add(2);
c.add(3);
c.add(4);
Iterator it=c.iterator();
while(it.hasNext()) {
System.out.println(it.next());
it.remove();
}
}
上述代码的while循环中,it.remove()方法删除的元素是当前迭代器指向的元素,故一定要放在it.next()方法之后,因为迭代器的初始值指向的是第一个元素的前一个位置,执行了next方法后在能删除元素,否则会出异常。
深入理解contains方法
深入理解remove方法
remove方法与contains方法一样,底层都会调用equals方法,故自定义的类所创建的对象,如果要方法集合中,一定要重写equals方法,否则只会比较地址,而不是比较内容。
List接口中常用方法
注意:以下方法要用ArrayList类进行实例化,用Collection接口不行。
void add(int index,Object element);在指定位置插入元素
Object get(int index);获取指定位置的元素
int indexof(Object o);获取指定元素的索引值,若有多个相同元素,则获取第一次出现的索引值。
int lastIndexOf(Object o);获取指定元素最后一次出现的索引值。
Object remove(int index);删除指定索引值的元素,并返回该元素。
Object set(int index,Object element);修改指定索引值元素,并返回旧值。
ArrayList集合的特点
1、ArrayList集合初始化默认容量是0,加入一个元素后变为10(十进制)ArrayList.class源码中有一个常量如下:
private static final int DEFAULT_CAPACITY = 10;
当容量不足时,底层数组容量会右移一位再加上原容量,底层代码是。
int newCapacity = oldCapacity + (oldCapacity >> 1);
由于底层是数组,为了提高资源利用率,初始化集合时可以先预估元素数量,先给个自定义初始化容量。
使用数组的优缺点:
优点:检索效率高(内存地址连续)
缺点:随机增删元素效率低,因为要移动多个元素。(但由于集合添加元素一般都是在集合末尾添加,增删元素效率不受影响,故ArrayList集合用的较多。LinkedList集合底层是链表是双向链表,虽然随机增删效率高,但检索效率低。)
2、ArrayList集合还有一个特殊的构造方法(源码如下):
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
即可以把另外一个集合变为ArrayList集合,如:
public static void main(String[] args) {
Collection c=new HashSet();
c.add("a");
c.add("b");
c.add("c");
c.add("d");
c.add("a");
ArrayList c1=new ArrayList(c);
Iterator it=c.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
上述代码把HashSet集合转为ArrayList集合。
LinkedList集合的特点
Set集合的特点
HashSet集合的特点(底层是HashMap,HashMap底层是哈希表)
1、存储和取出的顺序不同,不会按大小自动排序。
2、不可重复
3、放到HashSet集合的元素实际是放到HashMap集合的key部分(Set集合元素不可重复主要是Map集合key部分不可重复。)
如下列代码:
Set<String> strs=new HashSet<String>();
strs.add("A");
strs.add("B");
strs.add("Z");
strs.add("Y");
strs.add("Z");
strs.add("K");
strs.add("M");
for(String s:strs) {
System.out.print(s);
}
输出结果为ABYZKM。(不会自动排序)
TreeSet集合特点(底层是TreeMap,TreeMap底层是二叉树)
无序不可重复,但存储的元素可以自动按照大小顺序排序!(这里的无序是指取出来与放进去的顺序不同,但集合内会自动排序,遍历的结果是从小到大的排序。)
以上代码的集合若改为TreeSet,输出结果为ABKMYZ(会自动排序)。