创建集合对象的两种方式:
- 使用list接口 new 实现类
- 使用ArrayList声明对象, 泛型传的类型不能是基本数据类型,只能是引用数据类型,即包装类
集合的增删改查方法:
- 添加add(Object obj)
- add(int index,Object obj)在指定索引位置添加元素对象
- addAll(Collection c)以追加的方式将指定集合中的元素添加进另一个集合中
- 删除remove(Object obj) 根据对象删除集合元素,返回原始元素对象 remove(int index)根据索引删除集合元素,返回原始元素对象
- removeAll() 删除list1和list2中全部公共的集合元素,只留下非公共的集合元素
- retainAll() 删除list1和list2中全部非公共的集合元素,只留下公共的集合元素
- 设置set(int index)根据索引位置设置元素对象,返回原始元素对象
- get(int index)根据索引位置获取元素对象
- clear()清空集合中所有元素对象
- contains(Object obj) 判断指定对象在集合中是否存在
- containsAll() 返回boolean类型结果 检验list2中的所有集合元素是否存在list1集合中
- indexOf(Object obj)根据内容查找元素在集合中的位置,查找到直接返回索引位置,否则返回-1
- isEmpty() 检查集合是否为空,返回boolean类型
- size()查询集合中元素的个数
遍历List集合的三种方式:
- 从jdk1.5开始可以使用 增强for循环 遍历
- 因为list集合有索引,所以可以使用 普通for循环 遍历
- 当不清楚集合中有多少个元素对象,则需要使用迭代器遍历集合元素对象,Iterator迭代器用来迭代Collection下的所有集合,即List和set集合;ListIterator只能用来迭代List集合
Iterator正向遍历:使用迭代器之前先获取到Iterator对象。
ListIterator逆向遍历:【注意】唯有正向遍历之后才能使用逆向遍历
迭代器的使用-优化
常用:使用这种方式生成的list对象只有外部类在内存中被销毁时才被销毁
Iterator lte = list.iterator();
while(ite.hasNext()) {
System.out.println(ite.next());
}
优化:优化后的迭代方式是将list对象放入for循环代码块内,属于局部变量,当for循环结束时,list对象就会被释放掉,极大的节省了内存空间
for(Iterator lte = list.iterator();ite.hasNext();) {
System.out.println(ite.next());
}
迭代器源码分析
//List集合中的元素:
List list = new ArrayList();
list.add("hello");
list.add("java");
list.add("world");
//使用Iterator迭代器:
for(Iterator list = list.iterator();list.hasNext();) {
System.out.println(list.next());
}
//Iterator迭代器源码分析:
private class Itr implements Iterator<E> {
int cursor;//相当于指针 ,返回元素下一个索引 不初始化, 默认为0 // index of next element to return
int lastRet = -1;//如果下一个没有元素,则返回-1 // index of last element returned; -1 if no such
int expectedModCount = modCount;
// prevent creating a synthetic constructor
Itr() {}
public boolean hasNext() {
return cursor != size;//通过判断指针是否指向集合中最后一个元素,来判断集合中是否有元素
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;//值为0
/*保证程序健壮性代码
if (i >= size)
throw new NoSuchElementException();
*/
Object[] elementData = ArrayList.this.elementData;//将list数组给到一个新的Object数组
/*保证程序健壮性代码
if (i >= elementData.length)
throw new ConcurrentModificationException();
*/
cursor = i + 1;//指针后移一位
return (E) elementData[lastRet = i];//返回cursor指向0位置数组的值
}
迭代器遍历集合的实现过程原理:
- 当list迭代器对象被创建之后,先通过cursor指针是否指向集合中最后一个元素来判断集合中下一个是否有数据
- 如果有数据,则执行list.next():将指针cursor移向下一位,最后将指针(移动前的索引)指向的数据返回
- 如果没有数据,hasNext()返回false,终止while循环
hasNext():
返回boolean类型的值/判断集合中是否有元素对象,有元素对象才取出(集合初始时指针在集合头上一个位置,.hasNext()判断集合是否有下一个数据
hasPrevious():
判断集合是否有上一个数据
功能测试代码:
package pers.sheng.demo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Scanner;
public class TestArrayList {
public static void main(String[] args) {
// 创建集合对象的两种方式:
// 一、使用list接口new 实现类
List list1 = new ArrayList();
// 二、使用ArrayList声明对象 泛型传的类型不能是基本数据类型,只能是引用数据类型,即包装类
ArrayList<String> list2 = new ArrayList<>();
// 集合的增删改查方法:
// (1)添加add (Object obj)
list1.add("hello");
list1.add(123);//123int基本数据类型自动装箱成integer引用数据类型
list1.add(new Scanner(System.in));
// (2)集合中元素的个数size()
System.out.println(list1.size());
// (3)检查集合是否为空,返回boolean类型
System.out.println("集合是否为空:"+list1.isEmpty());
// (4)addAll(Collection c)以追加的方式将指定集合中的元素添加进另一个集合中
list2.add("hello");
list2.add("123");
list1.addAll(list2);
System.out.println("list1集合中元素的个数:"+list1.size());
System.out.println(list1);//遍历list集合的元素,直接输出list
// (5)删除remove(Object obj) 根据对象删除集合元素
System.out.println("根据对象删除集合元素:");
list1.remove("hello");
System.out.println(list1);
// list1.remove(123);【会报错,抛出数组索引超出边界异常】
// 要想将int类型根据对象删除,必须将基本dint基本数据类型装箱成integer包装类,否则会当成索引去检索集合元素是
list1.remove(Integer.valueOf(123));//Integer装箱采用.valueOf 而new Integer()已过时
// 以上装箱成Integer之后 删除掉Integer的数据123 留下了String类型的“123” 所以在(7)执行retainAll()方法时 123的类型均为String 视为相同元素
System.out.println(list1);
// 根据索引删除集合元素remove(int index)
list1.remove(0);
System.out.println(list1);
list1.add("world");//list1 [hello,123,world] list2 [hello,123]
// (6)removeAll() 删除list1和list2中全部公共的集合元素,只留下非公共的集合元素
// list1.removeAll(list2);
// System.out.println(list1);
// (7)retainAll() 删除list1和list2中全部非公共的集合元素,只留下公共的集合元素
// list1.retainAll(list2);
// System.out.println(list1);
// (8)判断指定对象在集合中是否存在contains(Object obj)
System.out.println("hello在集合中是否存在:"+list1.contains("hello"));
System.out.println("java在集合中是否存在:"+list1.contains("java"));
// (9)containsAll() 返回boolean类型结果 检验list2中的所有集合元素是否存在list1集合中
System.out.println(list1);
System.out.println(list2);
System.out.println(list1.containsAll(list2));
// (10)clear()清空集合中所有元素对象
// list1.clear();
System.out.println(list1);
// (11)get(int index)根据索引位置获取元素对象
System.out.println(list1.get(1));
// (12)set(int index)根据索引位置设置元素对象
list1.set(1, "java");
System.out.println(list1);
// (13)add(int index,Object obj)在指定索引位置添加元素对象
list1.add(1, "html");
System.out.println(list1);
// (14)indexOf()根据内容查找元素在集合中的位置,查找到直接返回索引位置,否则返回-1
System.out.println(list1.indexOf("java")+"\t"+list1.indexOf("sql"));
// (15)遍历集合中元素的内容
/* 1、从jdk1.5开始可以使用增强for循环遍历 */
System.out.println("使用for-each循环遍历集合中的元素\n");
for(Object obj:list1) {
System.out.println(obj);
}
/* 2、因为list集合有索引,所以可以使用普通for循环遍历 */
System.out.println("使用普通for循环遍历集合中的元素,根据list提供的get(int index)获取集合每个元素对象\n");
for(int i=0;i<list1.size();i++) {
System.out.println(list1.get(i));
}
/* 3、当不清楚集合中有多少个元素对象,则需要使用迭代器遍历集合元素对象 【正向遍历】*/
System.out.println("使用Iterator迭代器遍历list集合\n");
// 使用迭代器之前先获取到Iterator对象
Iterator ite = list1.iterator();
while(ite.hasNext()) {//返回boolean类型的值/判断集合中是否有元素对象,有元素对象才取出(集合初始时指针在集合头上一个位置,.hasNext()判断集合是否有下一个数据)
System.out.println(ite.next());//.next()指针往下移动的同时返回元素对象
}
/* 【逆向遍历】 listIterator() 【注意】唯有正向遍历之后才能使用逆向遍历*/
System.out.println("使用listIterator()正向遍历\n");
ListIterator listIte = list1.listIterator();
System.out.println("到达集合的开头,后面还有元素对象么?"+listIte.hasNext());
System.out.println("到达集合的开头,前面有元素对象么?"+listIte.hasPrevious());
// 先进行正向遍历
while(listIte.hasNext()) {
System.out.println(listIte.next());
}
System.out.println("到达集合的末尾,后面还有元素对象么?"+listIte.hasNext());
System.out.println("到达集合的末尾,前面有元素对象么?"+listIte.hasPrevious());
// 逆向遍历集合
System.out.println("使用listIterator()逆向遍历\n");
while(listIte.hasPrevious()) {
System.out.println(listIte.previous());
}
}
}