1.1集合的理解以及好处
使用数组的缺点:
1)长度必须在声明时确定,且确定后不能再更改。 2)保存的必须是同一种数据类型。 3)对数组增加或删除元素比较麻烦。 |
集合的好处:
1)不需要声明长度,在使用过程中会自动扩容。 2)可用动态的保存任意对象。 3)提供了一系列方便操作对象的,add,remove,set,get等 |
1.2集合的分类
集合主要分成两大类Collection接口实现类和Map接口实现类。
1)Collection的实现类都是单列集合
2)Map的实现类是双列集合
Collection接口框架 |
接口框架 |
public class Collection_ {
public static void main(String[] args) {
//单列集合
ArrayList arrayList = new ArrayList();
arrayList.add("lutao");
System.out.println(arrayList);
//双列集合
HashMap hashMap = new HashMap();
hashMap.put("lutao","shuaige"); //lutao = shuaige
System.out.println(hashMap);
}
}
2.1Collection实现类的特点
1)Collection没有直接实现子类,是通子接口List 和set 来实现。
2)实现List接口的是有序的 ,实现Set接口的是无序的(即添加与输出的顺序不同)。
3)Collection实现类中,有些是可以重复的,有些是不能重复的。
3)可以存放多个单列Object类元素。
2.2Collection实现类的常用方法
public class Collection_Method {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
//add:添加单个元素,可以添加Object的子类
arrayList.add("lutao");
arrayList.add(10); //Integer类型
arrayList.add(true);//Boolean类型
System.out.println(arrayList);
ArrayList arrayList1 = new ArrayList(arrayList);
//addAll 添加一个集合
arrayList1.addAll(arrayList);
System.out.println(arrayList1);
//向指定一个位置添加一个集合
arrayList1.addAll(1,arrayList);
System.out.println(arrayList1);
//size 获取元素的个数
System.out.println(arrayList1.size());
//contains 查看集合中是否存在该元素
System.out.println(arrayList1.contains(true));
//remove:删除一个元素
arrayList1.remove(true);
System.out.println(arrayList1);
//removeAll输出集合中的所以元素。
arrayList1.removeAll(arrayList);
System.out.println(arrayList1);
//isEmpty 查看集合是否为空
System.out.println(arrayList.isEmpty());
//clear //清空集合
arrayList.clear();
System.out.println(arrayList);
}
}
2.3Collecton实现类的遍历方法(三种)
1.使用Iterator(迭代器)遍历
Iterator对象称为迭代器,主要用于遍历Collection实现类集合中的元素,
每个实现Collection接口的类都可以调用iterator方法,返回一个迭代器,iterator仅用于遍历。
Iterator接口的方法
Collection list = new ArrayList();
list.add(new Book("三国演义","罗贯中",99.0));
list.add(new Book("西游记","吴承恩",99.0));
list.add(new Book("水浒传","施耐庵",99.0));
System.out.println(list);
//生成一个迭代器对象
Iterator iterator = list.iterator();
//hasNext()判断是否还有下一个元素
//next()返回下一个元素
while (iterator.hasNext()) { //快捷键itit
Object next = iterator.next();
System.out.println(next);
}
//遍历一次后next()处于最后一个元素,需要重置后才可以再次遍历,不然会报NoSuchElementException
iterator = list.iterator();
2.使用增强for(底层也是使用迭代器)循环遍历
Collection list = new ArrayList();
list.add(new Book("三国演义","罗贯中",99.0));
list.add(new Book("西游记","吴承恩",99.0));
list.add(new Book("水浒传","施耐庵",99.0));
//底层也是使用的迭代器遍历
for (Object book : list) { //快捷键I
System.out.println("Book="+book);
}
//数组
int[] arr = {1,23,4,5,6,7,83,3};
for (int i : arr) {
System.out.print(i+" ");
}
3.1List接口的特点
1)List是Collection接口的子接口。
2)List接口中类的集合是有序的,而且元素可以重复。
3)List集合中,每一个元素都有其对应的顺序索引(支持索引),且有一个序号记录其位置。
4)List接口的常用实现类有Vector、ArrayList、LinkedList。
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
/*Listd的常用方法*/
//1.add在指定位置插入ele元素 addAll将集合中的所有元素从该索引加入
list.add(0,"lutao");
System.out.println(list);
//2.get 获取指定位置的元素
System.out.println(list.get(0));
//3.IndexOf获取元素在集合中首次出现的位置
//4.lastIndexOf获取元素在集合中最后一次出现的位置
//5.remove移除指定位置的元素并,并返回该元素
System.out.println(list.remove(0));
System.out.println(list);
//6.set(index,ele)将指定位置的元素设置成ele
list.set(0,"小七");
System.out.println(list);
//7.subList(fromIndex,toIndex);返回从fromIndex到toIndex的子集合,但不包括toIndex
List toList = list.subList(1,3);
System.out.println(toList);
toList.add(1);
System.out.println(toList);
3.3List接口的遍历方式
可以使用三种遍历方式
1)Iterator迭代器
2)增强for循环
3)普通for循环
4.1ArrayList创建与扩容机制
1)ArrayList底层维护的是一个Object类的数组elementData( transient Object[] elementData)。
2)创建ArrayList对象时,如果调用的是无参构造方法,则elementData的初始容量为0,
第一次添加则扩容为10,之后的每一次扩容为elementDate的1.5倍。
3)如果是指定大小的构造器,则elementDate初始为指定大小,后面的每一次增持elementData的1.5倍。
ArrayList的创建
elementData的扩容
5.1Vector的特点
1)Vector底层也是一个对象数组,protected Object[] elementData,与ArrayList基本相同,Vector的操作方法带有synchronized 所以Vector是线程安全的。
ArrayList与Vector的比较
ArrayList | 不安全,效率高 | 如果有参,每次1.5倍 如果无参,1)10,然后每次1.5 |
Vector | 安全,效率不高 | 如果有参,每次2倍 如果无参,1)10,然后每次2.0 |
6.1LinkedList类的特点
1)LinkedList底层实现了双向链表和双端队列的特点。
2)可以添加任意元素(可以重复、支持null)
3)线程不安全,没有实现同步
底层结构:
1)LinkedList底层维护的是一个双向链表(对元素的增删更佳高效)
2)维护了两个Node类的属性first和last,分别指向链表的第一个结点(对象)和最后一个结点。
3)每个结点里面维护了三个属性item是实际存放的元素,
通过prev指向前一个结点,,通过next指向后一个结点,从而实现双链表。
| Node是一个内部类 |
结构图 |
Node jack = new Node("jack");
Node tom = new Node("tom");
Node lutao = new Node("lutao");
Node first = jack;
Node last = lutao;
//后缀
jack.next = tom;
tom.next = lutao;
//前缀
lutao.pre = tom;
tom.pre = jack;
//遍历 >从头到尾
System.out.println("=====从头到尾遍历=====");
while(true){
if (first == null){
break;
}
System.out.println(first);
first = first.next;
}
first = jack;
class Node{
public Object item; //存放数据
public Node next; //指向后缀
public Node pre; //指向前缀
public Node(Object name) {
this.item = name;
}
public String toString() {
return "Node name=" + item;
}
}
6.2ArrayList和LinkedList的比较
底层结构 | 增删效率 | 改查效率 | |
ArrayList | 可变数组 | 较低(数组扩容) | 较高 |
LinkedList | 双向链表 | 较高(链表追加) | 较低 |