JAVA集合框架(二)
文章目录
二. List接口与实现类
- 特点:有序、有下标、元素可以重复。
1. List接口
集合遍历:
例一:
import java.util.*;
public class Application {
public static void main(String[] args) {
//创建一个集合
List list = new ArrayList();
//添加元素
list.add("苹果");
list.add("香蕉");
list.add(0,"草莓");
System.out.println(list);
//删除元素
// list.remove("苹果");
// list.remove(0);
// System.out.println(list);
//判断
System.out.println("是否包含'苹果':"+list.contains("苹果"));
System.out.println("是否为空:"+list.isEmpty());
//获取
System.out.println("苹果的下标为:"+list.indexOf("苹果"));
//遍历
//for()
System.out.println("----------for--------");
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
//增强for
System.out.println("----------增强for--------");
for (Object o : list) {
System.out.println(o);
}
System.out.println("----------迭代器---------");
//迭代器
Iterator iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//列表迭代器 和iterator的区别:ListIterator可以向前或向后遍历,添加,删除,修改元素
ListIterator listIterator = list.listIterator();
System.out.println("---------list迭代器从前到后:-----------");
while (listIterator.hasNext()){
System.out.print(listIterator.nextIndex()+"\t");
System.out.println(listIterator.next());
}
System.out.println("---------list迭代器从后到前:-----------");
while (listIterator.hasPrevious()){
System.out.print(listIterator.previousIndex()+"\t");
System.out.println(listIterator.previous());
}
}
}
---------------结果---------------
[草莓, 苹果, 香蕉]
是否包含'苹果':true
是否为空:false
苹果的下标为:1
----------for--------
草莓
苹果
香蕉
----------增强for--------
草莓
苹果
香蕉
----------迭代器---------
草莓
苹果
香蕉
---------list迭代器从前到后:-----------
0 草莓
1 苹果
2 香蕉
---------list迭代器从后到前:-----------
2 香蕉
1 苹果
0 草莓
例二:
import java.util.*;
public class Application {
public static void main(String[] args) {
List list= new ArrayList();
//添加数字类型:隐藏了自动装箱操作
list.add(10);
list.add(20);
list.add(30);
list.add(40);
System.out.println(list.size());
System.out.println(list);
//删除
list.remove((Object) 10);
list.remove(new Integer(20));//包装
//不可直接用list.remove(10); 会把10当成下标来删除,导致下标越界
System.out.println(list);
}
}
---------------结果---------------
4
[10, 20, 30, 40]
[30, 40]
add()方法
void add(int index,Object o)//在index位置插入对象o。
import java.util.ArrayList;
import java.util.List;
public class Application {
public static void main(String[] args) {
List list = new ArrayList();
list.add(0,"苹果");
list.add(1,"香蕉");
list.add(2,"草莓");
list.add(0,"菠萝");
System.out.println(list);
}
}
----------------结果-----------------
[菠萝, 苹果, 香蕉, 草莓]
addAll()方法
boolean addAll(int index,Collection c)//将一个集合中的元素添加到此集合中的index位置。
import java.util.ArrayList;
import java.util.List;
public class Application {
public static void main(String[] args) {
List list = new ArrayList();
List list2 = new ArrayList();
list.add(0,"苹果");
list.add(1,"香蕉");
list2.add(0,"草莓");
list2.add(1,"菠萝");
System.out.println(list);
System.out.println(list2);
list2.addAll(1,list);
System.out.println(list2);
}
}
---------------结果---------------
[苹果, 香蕉]
[草莓, 菠萝]
[草莓, 菠萝]
get()方法
0bject get(int index)//返回集合中指定位置的元素。
import java.util.ArrayList;
import java.util.List;
public class Application {
public static void main(String[] args) {
List list = new ArrayList();
list.add(0,"苹果");
list.add(1,"香蕉");
list.add(2,"草莓");
System.out.println(list);
System.out.println(list.get(0));
}
}
---------------结果---------------
[苹果, 香蕉, 草莓]
苹果
subList()方法
List subList(int fromIndex,int toIndex)//返回fromIndex和toIndex之间的集合元素。
import java.util.ArrayList;
import java.util.List;
public class Application {
public static void main(String[] args) {
List list = new ArrayList();
list.add(0,"苹果");
list.add(1,"香蕉");
list.add(2,"草莓");
System.out.println(list);
System.out.println(list.subList(1,3));//包含下界,不含上界
}
}
---------------结果---------------
[苹果, 香蕉, 草莓]
[香蕉, 草莓]
2. List实现类
- ArrayList【重点】:
数组结构实现,查询快、增删慢;
JDK1.2版本,运行效率快、线程不安全。 - Vector:
数组结构实现,查询快、增删慢;
JDK1.0版本,运行效率慢、线程安全。 - LinkedList:
链表结构实现,增删快,查询慢。
ArrayList集合:
- 数组结构实现,查询快、增删慢;
- JDK1.2版本,运行效率快、线程不安全。
import java.util.*;
public class Application {
public static void main(String[] args) {
//ArrayList实现类
//存储结构:数组,查找遍历速度快,增删速度慢
//创建集合
ArrayList arrayList = new ArrayList();
//增加元素
Student s1 = new Student("aaa", 20);
Student s2 =new Student("bbb",20);
Student s3 =new Student("ccc",20);
Student s4 =new Student("ddd",20);
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
arrayList.add(s4);
System.out.println("元素个数为:"+arrayList.size());
System.out.println(arrayList);
//删除元素
arrayList.remove(s1);
System.out.println(arrayList);
arrayList.remove(new Student("bbb",20));//相当于用了equals方法,比较地址,不相同则无法删除
//解决方法重写equals方法
System.out.println(arrayList);
//遍历元素
//迭代器
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//列表迭代器
ListIterator listIterator = arrayList.listIterator();
while (listIterator.hasNext()){
System.out.println(listIterator.nextIndex()+":\t"+listIterator.next());
}
//判断
System.out.println("包含学生s3吗\t"+arrayList.contains(s3));
System.out.println("包含学生s4吗\t"+arrayList.contains(new Student("ddd", 20)));
System.out.println("是否为空\t"+arrayList.isEmpty());
//查找
System.out.println("查找s4的下标为\t"+arrayList.indexOf(s4));
}
}
---------------结果---------------
元素个数为:4
[[name=aaa, age=20], [name=bbb, age=20], [name=ccc, age=20], [name=ddd, age=20]]
[[name=bbb, age=20], [name=ccc, age=20], [name=ddd, age=20]]
[[name=ccc, age=20], [name=ddd, age=20]]
[name=ccc, age=20]
[name=ddd, age=20]
0: [name=ccc, age=20]
1: [name=ddd, age=20]
包含学生s3吗 true
包含学生s4吗 true
是否为空 false
查找s4的下标为 1
public class Student {
private String name;
private int age;
public Student(String name, int age) {
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 "[name="+name+", age="+age+"]";
}
@Override
public boolean equals(Object obj) {
//是否是同一个对象
if(this==obj){
return true;
}
//是否是同为空
if(obj==null){
return false;
}
//判断是否是Student类
if(obj instanceof Student){
Student s =(Student)obj;
//比较属性
if(this.name.equals(s.getName()) && this.age==s.getAge()){
return true;
}
}
//不满足,返回false
return false;
}
}
ArrayList源码分析
默认容量大小: DEFAULT_CAPACITY = 10;(添加元素之后,没有添加时为0)
存放元素的数组: elementData
实际元素个数:size
add添加元素(源码):
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));//第一次执行相当于ensureExplicitCapacity(10);
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);//当第一次add时,DEFAULT_CAPACITY=10,minCapacity=1
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0) //10>0
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; //oldCapacity=0;
int newCapacity = oldCapacity + (oldCapacity >> 1); //newCapacity=0+0;
if (newCapacity - minCapacity < 0) //0-10 < 0
newCapacity = minCapacity; //newCapacity=10;
if (newCapacity - MAX_ARRAY_SIZE > 0) //MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8 肯定是假
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity); //创建新数组,长度为10,内容为空
}
当添加在10个以内的时候,容量为10,到存储第11个时,扩容为15个,之后每次扩容大小为最大容量的1.5倍。
Vector集合(了解)
- 数组结构实现,查询快、增删慢;
- JDK1.0版本,运行效率慢、线程安全。
import java.util.Enumeration;
import java.util.Vector;
public class Application {
public static void main(String[] args) {
//创建集合
Vector vector = new Vector();
//添加元素
vector.add("aaa");
vector.add("bbb");
vector.add("ccc");
System.out.println("元素个数为:"+vector.size());
//删除
//vector.remove(0);
//vector.remove("ccc");
//vector.clear();
//枚举器遍历
Enumeration elements = vector.elements();
while (elements.hasMoreElements()){
System.out.println(elements.nextElement());
}
System.out.println("是否包含 ccc :"+vector.contains("ccc"));
System.out.println("是否为空:"+vector.isEmpty());
//其他方法
System.out.println("第一个元素:"+vector.firstElement());
System.out.println("最后一个元素:"+vector.lastElement());
System.out.println("获取0号元素:"+vector.elementAt(0));//获取元素
System.out.println("获取2号元素:"+vector.get(2));//获取元素
}
}
---------------结果---------------
元素个数为:3
aaa
bbb
ccc
是否包含 ccc :true
是否为空:false
第一个元素:aaa
最后一个元素:ccc
获取0号元素:aaa
获取2号元素:ccc
LinkedList集合
- 双向链表结构实现,增删快,查询慢。
import java.util.*;
public class Application {
public static void main(String[] args) {
//创建集合
LinkedList linkedList = new LinkedList();
Student s1 = new Student("张三", 20);
Student s2 = new Student("李四", 20);
Student s3 = new Student("王五", 20);
linkedList.add(s1);
linkedList.add(s2);
linkedList.add(s3);
linkedList.add(s3);
System.out.println("元素个数为:"+linkedList.size());
System.out.println(linkedList);
//删除
linkedList.remove(new Student("王五", 20));
System.out.println(linkedList);
//linkedList.clear();
//遍历
System.out.println("-----------for-----------");
for(int i=0;i<linkedList.size();i++){
System.out.println(linkedList.get(i));
}
System.out.println("---------增强for----------");
for (Object o : linkedList) {
//System.out.println((Student) o);
System.out.println(o);
}
System.out.println("---------迭代器----------");
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()){
//System.out.println((Student) iterator.next());
System.out.println(iterator.next());
}
System.out.println("---------list迭代器----------");
ListIterator listIterator = linkedList.listIterator();
while (listIterator.hasNext()){
System.out.println(listIterator.nextIndex()+"\t"+listIterator.next());
}
//判断
System.out.println("是否包含s2:"+linkedList.contains(s2));
System.out.println("是否为空:"+linkedList.isEmpty());
//获取
System.out.println("获取s2所在下标:"+linkedList.indexOf(s2));
}
}
---------------结果---------------
元素个数为:4
[[name=张三, age=20], [name=李四, age=20], [name=王五, age=20], [name=王五, age=20]]
[[name=张三, age=20], [name=李四, age=20], [name=王五, age=20]]
-----------for-----------
[name=张三, age=20]
[name=李四, age=20]
[name=王五, age=20]
---------增强for----------
[name=张三, age=20]
[name=李四, age=20]
[name=王五, age=20]
---------迭代器----------
[name=张三, age=20]
[name=李四, age=20]
[name=王五, age=20]
---------list迭代器----------
0 [name=张三, age=20]
1 [name=李四, age=20]
2 [name=王五, age=20]
是否包含s2:true
是否为空:false
获取s2所在下标:1
LinkedList源码分析
创建集合时:
transient int size = 0; 集合大小=0,还没有添加
transient Node first; 指向第一个元素,为空
transient Node last; 指向最后一个元素,为空
第一次添加时:
public boolean add(E e) {
linkLast(e);//链接到最后一个位置
return true;
}
void linkLast(E e) {
final Node<E> l = last; //添加时为一个节点,类型就是这个Node
final Node<E> newNode = new Node<>(l, e, null);// l为prev=null ,e为当前数据,null为next
//当创建第二个的时候,l=头节点,把prev赋值为头节点
last = newNode;//第一次执行时将尾赋值为刚创建的节点
if (l == null)
first = newNode;//第一次执行时把头也赋值为第一个创建的节点,
else
l.next = newNode;//第二次创建时,头的next指向第二个节点(双向链表)
size++;
modCount++;
}
private static class Node<E> {
E item; //实际数据
Node<E> next;//下一个节点
Node<E> prev;//前一个节点
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
ArrayList和LinkedList的区别
ArrayList是一个数组
LinkedList是一个双向链表,结构差不多如下图所示:
ArrayList:必须开辟连续空间,查询快,增删慢。
LinkedList:无需开辟连续空间,查询慢,增删快。