一阶段:第10天:集合框架List(8.5)
一.概述
1.1集合与数组的对比
- 相同点:都是数据的容器,在一个数组或集合中可以存储多个数据
- 不同点:
(1)元素:
数组中可以存储基本类型和引用类型
集合只能存储引用类型(装箱)
(2)长度(元素个数):
数组是定长的,一旦初始化长度就不可以修改
集合长度可以修改,可以删除元素和添加元素
二. Collection接口
Collection 层次结构中的根接口。因为是接口,所以得通过子类对象来实现(List和Set)
Collection 表示一组对象,这些对象也称为 collection 的元素。
一些 collection 允许有重复的元素,而另一些则不允许。
一些 collection 是有序的,而另一些则是无序的。
List派系:可以重复、有序
Set派系:不能重复、无序
常用方法:
方法名 | 描述 |
---|---|
add(E e) | 确保此 collection 包含指定的元素(可选操作)。 |
clear() | 移除此 collection 中的所有元素(可选操作)。 |
contains(Object o) | 如果此 collection 包含指定的元素,则返回true。 |
equals(Object o) | 比较此 collection 与指定对象是否相等。 |
isEmpty() | 如果此 collection 不包含元素,则返回true。 |
iterator() | 返回在此 collection 的元素上进行迭代的迭代器。 |
remove(Object o) | 从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。 |
size() | 返回此 collection 中的元素数。 |
toArray() | 返回包含此 collection 中所有元素的数组。 |
实例1
public class Demo1 {
public static void main(String[] args) {
//创建集合对象
Collection collection=new ArrayList();
//1.添加,可以有重复的数据
collection.add("少泊");
collection.add("少泊");
collection.add("凤姐");
System.out.println("元素的个数:"+collection.size());
System.out.println("打印:"+collection.toString());
//2.删除,只删除找到的第一个数据
collection.remove("少泊");
System.out.println("打印:"+collection.toString());
//清空
/*collection.clear();
System.out.println("清空之后:"+collection.toString());*/
//3.遍历
//3.1增强for,不能使用for,因为没有下标
//不允许边遍历,边删除
System.out.println("------增强for遍历---------");
for (Object o : collection) {
System.out.println(o);
//删除元素
//出现异常
// ConcurrentModificationException
//并发修改异常
//collection.remove(o);
}
//3.2使用迭代器
//可以使用迭代器remove()方法删除
System.out.println("-----迭代器-----");
Iterator it=collection.iterator();
while (it.hasNext()){
System.out.println(it.next());
//使用迭代器删除
//it.remove();
}
//4.判断
//4.1判断是否为空
System.out.println(collection.isEmpty());
//4.2判断是否存在
System.out.println(collection.contains("少泊"));
//5.其他方法
Collection nums1=new ArrayList();
nums1.add(4);
nums1.add(5);
nums1.add(6);
Collection nums2=new ArrayList();
nums2.add(7);
nums2.add(8);
nums2.add(9);
nums1.addAll(nums2);
System.out.println("nums1"+nums1.toString());
System.out.println(nums1.containsAll(nums2));
nums1.retainAll(nums2);//取交集
System.out.println("nums1"+nums1.toString());
nums1.removeAll(nums2);
System.out.println("nums1"+nums1.toString());
Object[] objects=collection.toArray();
System.out.println(Arrays.toString(objects));
}
}
三.泛型
3.1泛型的基本使用
<>钻石语法
泛型好处:
(1)不用类型转换,不会出现类型转换异常,安全
(2)提高代码重用性
泛型类:在类名后面加上(<>里也可以写别的大写字母表示),表示泛型,如果写多个泛型,可以用","隔开
E:Element
T:Type
K:Key
V:Value
泛型方法:在返回值的前面写上 E也可以作为返回值
泛型接口:在接口名的后面写上
public class Generic<E> {
//使用泛型定义成员变量
E e;
//泛型作为方法参数
public void show(E e){
this.e=e;
System.out.println(e);
}
//泛型作为返回值
public E get(){
return e;
}
}
public class Generic2 {
public <E> void show(E e){
System.out.println(e);
}
}
public class GDemo1 {
public static void main(String[] args) {
Generic<String> generic=new Generic<String>();//后边的String可以省略
generic.e="张三";
generic.show("李四");
String s=generic.get();
System.out.println(s);
Generic<Integer> generic1=new Generic<>();
generic1.e=100;
generic1.show(200);
Integer integer=generic1.get();
System.out.println(integer);
}
}
public interface MyInterface<E> {
void show(E e);
E get();
}
3.2受限泛型
上限类型和下限类型
1)<?>:表示任意类型
2)<? extends T>:表示T类或者T类的子类----->上限类型—上限是T类型
3)<? super T>:表示T类或者T类的父类-------->下限类型—至少得是T类型
public class Demo4 {
public static void main(String[] args) {
/*Generic<String> generic=new Generic<>();
Generic<Integer> generic1=new Generic<>();
generic.show("hello");
generic1.show(1000);*/
Generic<MStudent> generic=new Generic<>();
MStudent student=new MStudent();
student.name="张三";
generic.show(student);
print(generic);
//print(generic1);
Collection<String> names=new ArrayList<>();
names.add("小张");
names.add("小李");
print2(names);
}
//使用泛型对象作为方法参数,泛型中的参数不能修改
//泛型上限
/*public static void print(Generic<? extends MStudent> generic){
System.out.println(generic.get());
}*/
//泛型下限
public static void print(Generic<? super MStudent> generic){
System.out.println(generic.get());
}
public static void print2(Collection<?> collection){
for (Object o : collection) {
System.out.println(o);
}
}
}
3.3 List接口
- 相对有序存储,可以存储相同元素(不排重),可以通过下标访问集合元素
- List接口中可以使用独有的迭代器ListIterator,具有反向遍历的功能
方法名 | 描述 |
---|---|
add(int index, E element) | 在列表的指定位置插入指定元素(可选操作)。 |
addAll(int index, Collection<? extends E> c) | 将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。 |
containsAll(Collection<?> c) | 如果列表包含指定 collection 的所有元素,则返回true。 |
get(int index) | 返回列表中指定位置的元素。 |
indexOf(Object o) | 返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。 |
lastIndexOf(Object o) | 返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。 |
listIterator() | 返回此列表元素的列表迭代器(按适当顺序)。 |
remove(int index) | 移除列表中指定位置的元素(可选操作)。 |
set(int index, E element) | 用指定元素替换列表中指定位置的元素(可选操作)。 |
subList(int fromIndex, int toIndex) | 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。 |
3.3.1 ArrayList类
要重写equals方法
ArrayList类是List接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括null在内的所有元素。
存储特点:相对有序存储,可以存储相同元素(不排重),可以通过下标访问集合元素,通过数组实现的集合
存储结构:数组
public class ArrayListDemo {
public static void main(String[] args) {
//创建集合
ArrayList<String> arrayList=new ArrayList<>();
//添加
arrayList.add("梁朝伟");
arrayList.add("陈晓");
arrayList.add("陈妍希");
arrayList.add("杨紫");
System.out.println(arrayList.toString());
//删除
arrayList.remove(0);
//遍历
//1.增强for
System.out.println("增强for");
for (String s : arrayList) {
System.out.println(s);
}
//迭代器
System.out.println("迭代器");
ListIterator<String> it=arrayList.listIterator();
while (it.hasNext()){
System.out.println(it.next());
}
System.out.println("--------");
while (it.hasPrevious()){
System.out.println(it.previous());
}
}
}
public class ArrayListDemo2 {
public static void main(String[] args) {
ArrayList<Student> students=new ArrayList<>();
students.add(new Student("z1",18));
students.add(new Student("z2",19));
students.add(new Student("z2",22));
System.out.println(students.toString());
//删除(依据是什么?equals方法的返回值)
students.remove(new Student("z1",18));
System.out.println("删除之后:"+students.toString());
//遍历
for (Student student : students) {
System.out.println(student);
}
//判断
//判断是否存在
System.out.println(students.contains(new Student("z2",19)));
//获取位置
System.out.println(students.indexOf(new Student("z2",22)));
}
}
3.3.2 LinkedList类
LinkedList类是List接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括null)。
存储结构:双向链表
存储特点:相对有序存储,可以存储相同元素(不排重),可以通过下标访问集合元素,通过链表实现的集合
public class LinkListDemo {
public static void main(String[] args) {
//创建集合
LinkedList<String> linkedList= new LinkedList();
//添加元素
linkedList.add("张三");
linkedList.add("李四");
linkedList.add("王五");
System.out.println(linkedList.toString());
//删除
linkedList.removeFirst();
System.out.println("删除之后:"+linkedList);
//遍历
//增强for
for (String s : linkedList) {
System.out.println(s);
}
//迭代器
Iterator<String> it=linkedList.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
// 使用LinkList实现队列
// 特点:先进先出
public class LinkListDemo2 {
public static void main(String[] args) {
//创建对象
Queue<String> queue=new LinkedList<>();
//添加元素
queue.add("张三");
queue.add("李四");
queue.add("王五");
queue.add("赵柳");
queue.add("少泊");
//实现队列出队操作
for (int i=0;i<5;i++){
System.out.println(queue.poll());
}
System.out.println("执行完:"+queue.size());
}
}
public class ListDemo {
public static void main(String[] args) {
//创建集合对象
List<String> list=new ArrayList<>();
//添加
//接口没有继承Object,但是可以通过实现类调用Object中的方法(因为实例一定继承了Object)
list.add("苹果");
list.add("酥梨");
list.add("西瓜");
list.add("香蕉");
list.add("桃子");
list.add("西瓜");
System.out.println("打印"+list.toString());
//删除
list.remove("西瓜");
list.remove(0);
System.out.println("删除之后:"+list.toString());
//遍历
//增强for
for (String s : list) {
System.out.println(s);
}
//迭代器
Iterator<String> it=list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//使用for
for (int i = 0; i <list.size() ; i++) {
System.out.println(list.get(i));
}
//使用列表迭代器,向前向后遍历,删除,修改,添加
ListIterator<String> it2=list.listIterator();
System.out.println("---顺序遍历---");
//it2.add("芒果");
/*while (it2.hasNext()){
if (it2.nextIndex()==0){
it2.add("榴莲");
}
System.out.println(it2.next());
}*/
System.out.println("----逆序----");
while (it2.hasPrevious()){
System.out.println(it2.previous());
}
}
}
ArrayList存储结构是数组,LinkedList存储结构是双向链表。
ArrayList集合适用在对元素查询、遍历操作,不适合插入和删除。
LinkedList集合适用在对元素插入和删除操作,不适合遍历和查找。
3.3.3 Vector类
Vector类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是Vector的大小可以根据需要增大或缩小,以适应创建 Vector后进行添加或移除项的操作。
Stack类表示后进先出(LIFO)的对象栈。是Vector的子类。
public class VectorDemo {
public static void main(String[] args) {
Vector<String> vector=new Vector<>();
//添加元素
vector.add("华为");
vector.add("苹果");
Enumeration<String> elements=vector.elements();
while (elements.hasMoreElements()){
System.out.println(elements.nextElement());
}
}
}
public class StackDemo {
public static void main(String[] args) {
//创建集合
Stack<String> stack=new Stack<>();
stack.push("zzz");
stack.push("zza");
stack.push("zzb");
stack.push("zzc");
stack.push("zzd");
//站的操作
int size=stack.size();
for (int i=0;i<size;i++){
System.out.println(stack.pop());
}
System.out.println(stack.size());
}
}
public class StackDemo2 {
public static void main(String[] args) {
Deque<String> deque=new ArrayDeque<>();
//入栈
deque.addFirst("小张0");
deque.addFirst("小张1");
deque.addFirst("小张2");
//出栈
int size=deque.size();
for (int i=0;i<size;i++){
System.out.println(deque.removeFirst());
}
System.out.println("元素个数:"+deque.size());
}
}