【Java的集合框架之list 27】
一、list集合和set集合
Collection下面有两个派系:
|-- list:有序(存入和取出的顺序一致),元素都有索引(角标)。元素可以重复
|-- set:无序,元素不能重复
二、list集合:可以完成对元素的增删改查
list:除了有父类Collection的方法,还有一些特有的常见方法
有一个共性特点就是都可以操作角标
1、添加
void add (index,element) -->按照索引添加元素
void add (index,collection) -->按照索引添加集合
2、删除
object remove(index) -->按照索引删除元素
3、修改
Object set(index,element) -->按照索引修改元素
4、获取
Object get(index); -->按照索引获取元素
int indexOf(object) -->获取对象的索引
int lastIndexOf(object) -->获取对象的最后一个索引
List subList(from,to) -->获取从from到to索引的集合,from是闭区间,to是开区间
package com.JavaStudy01; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * @Author wufq * @Date 2020/7/30 14:13 */ public class ListDemo01 { public static void main(String[] args){ List list = new ArrayList(); show(list); } public static void show(List list) { //增加元素 list.add("ABC1"); list.add("ABC2"); list.add("ABC3"); //添加元素 list.add(1,"abc8"); System.out.println(list);//[ABC1, abc8, ABC2, ABC2] //删除指定元素 System.out.println("removeObject:"+list.remove("abc8"));//removeObject:true System.out.println("removeIndex:"+list.remove(2));//removeIndex:ABC2 System.out.println(list);//[ABC1, ABC2] //修改元素 list.set(1,"abc9"); System.out.println(list);//[ABC1, abc9] //获取 System.out.println(list.get(2));//ABC3 System.out.println(list.indexOf("ABC3"));//2 System.out.println(list.lastIndexOf("ABC2"));//1 System.out.println(list.subList(1,2));//[ABC2] //获取所有元素 //常规取出所有元素的方式 Iterator it=list.iterator(); while (it.hasNext()){ System.out.print(it.next()+" ");//ABC1 abc8 ABC2 ABC3 } System.out.print("\n"); //list特有的取出元素的方式:get for(int i=0;i<list.size();i++){ System.out.print(list.get(i)+" ");//ABC1 abc8 ABC2 ABC3 } } }
三、list的 listIterator接口
public interface ListIterator<E> extend Iterator<E> ListIterator继承了Iterator
List接口提供了特殊的迭代器,称为ListIterator,除了允许Iterator提供的正常的操作外,该迭代器还允许元素插入和替换,以及双向访问。还提供了一个方法来获取从列表中指定位置开始的列表迭代器
注意:只有list具备该迭代功能
listIterator接口的方法:
1、除了具备父类接口iterrator的hashnext()、next()、remove()方法,还具备自身的其他方法
2、boolean hasPrevious():逆向遍历列表,返回true
3、previous():向前查找 。例如:[1,2,3] 用此方法查找的是3,2,1
4、set():替换元素
package com.JavaStudy01; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; /** * @Author wufq * @Date 2020/7/30 15:43 */ public class ListDemo02 { public static void main(String[] args){ List list = new ArrayList(); listshow(list); } public static void listshow(List list) { list.add("abc1"); list.add("abc2"); list.add("abc3"); /* 需求:遍历list集合,如果遍历到abc2时,增加一个新元素abc9 */ //调用iterator接口 Iterator it=list.iterator(); while (it.hasNext()){ //查找下一个元素 Object obj =it.next(); if(obj.equals("abc2")){ list.add("abc9"); } } System.out.println(list); //异常:ConcurrentModificationException当方法检测到对象的并发修改时,但是又不允许修改,抛出异常 /* 抛出这个异常的原因是:Iterator对象在查找元素,而list又在修改,这时候Iterator其实是不知道list已经被修改了,所以就抛出了这个错误 改进的方法:是采用Iterator的子接口ListIterator,这个接口是可以进行修改的 */ //改进的方法 ListIterator lt=list.listIterator(); //正向遍历hasNext() while (lt.hasNext()){ Object obj=lt.next(); if(obj.equals("abc2")){ lt.add("abc9"); } } //反向遍历 while (lt.hasPrevious()){ } System.out.println("next:"+lt.next());//遍历后,查找下一个元素-->没有找到抛出java.util.NoSuchElementException System.out.println("previous:"+lt.previous());//向前查找 -->abc3 System.out.print(list); //[abc1, abc2, abc9, abc3] System.out.println(lt.nextIndex()); } }
四、list常用子类的特点
list常用的子类
|-- Vector:内部是数组数据结构,是同步的。增删查询都很慢。
|-- ArrayList:内部是数组数据结构,是不同步的。替代了Vector。查询速度快
|-- LinkedList:内部是链表数据结构,是不同步的。增删元素的速度很快
下图是数组和链表如何存储数据的原理,以及各数组和链表的优缺点
备注:数组是长度固定的,list是可变长度的,如何实现呢?
创建一个新数组,将原来的数组复制到新数组内,就实现了list长度的可变
数组、链表查询快慢的原因,如下图:
1、LinkedList集合
LinkedList除了继承了list里面常用的一些方法(除listIterator()方法),还有一些自有的方法,如:
|-- addfirst 在列表前头插入元素
|-- addlast 在列表后头插入元素
|-- getfirst 获取第一个元素但是不删除
|-- getlast 获取最后一个元素但是不删除
|-- removefirst 获取第一个元素但是会删除
|-- removelast 获取最后一个元素但是会删除
package com.JavaStudy01; import java.util.Iterator; import java.util.LinkedList; /** * @Author wufq * @Date 2020/7/31 09:43 */ public class LinkedListDemo01 { public static void main(String[] args){ LinkedList link = new LinkedList(); //在第一个元素前面插入元素、最后一个元素后面插入元素 link.addFirst("abc1"); link.addFirst("abc2"); link.addFirst("abc3"); link.addLast("abd4"); System.out.println(link);//[abc3, abc2, abc1, abd4] //迭代器获取里面所有的元素 Iterator li=link.iterator(); while (li.hasNext()){ System.out.println(li.next()); } //获取第一个元素或者最后一个元素 System.out.println(link.getFirst()); //abc3 -->获取元素但是不会删除列表内的元素 System.out.println(link.getFirst());//abc3 System.out.println(link.getLast());//abc3 System.out.println(link);//[abc3, abc2, abc1, abd4] //移除第一个元素或者最后一个元素 System.out.println(link.removeFirst());//abc3 -->获取元素但是会删除列表内的元素 System.out.println(link.removeFirst());//abc2 System.out.println(link.removeLast());//abd4 System.out.println(link);//[abc1] //循环删除列表内的元素 while (!link.isEmpty()){ System.out.println("removeFirst="+link.removeFirst()); } System.out.println("link="+link);//link=[] } }
---需求:使用LinkedList模拟一个堆栈和队列数据结构---
|-- 堆栈的数据结构:先进后出
|-- 队列的数据结构:先进先出
----队列类----
package com.JavaStudy01.LinkedListTest; import java.util.LinkedList; /** * @Author wufq * @Date 2020/7/31 10:38 */ public class DuiLie { private LinkedList link; public DuiLie(){ link = new LinkedList(); } //增加 public void myAdd(Object obj){ link.addLast(obj); } //获取 public Object getLink(){ return link.removeFirst(); } //判断 public boolean isNull(){ return link.isEmpty(); } }
----堆栈类----
package com.JavaStudy01.LinkedListTest; import java.util.LinkedList; /** * @Author wufq * @Date 2020/7/31 10:38 */ public class DuiZhan { private LinkedList link; DuiZhan(){ link = new LinkedList(); } //增加 public void myDZadd(Object obj){ link.addFirst(obj); } //获取 public Object getDZ(){ return link.removeFirst(); } //判断 public boolean dzisNull(){ return link.isEmpty(); } }
----main方法调用-----
package com.JavaStudy01.LinkedListTest; /** * @Author wufq * @Date 2020/7/31 10:13 */ public class LinkedListDemo02 { public static void main(String[] args){ DuiLie dl = new DuiLie(); dl.myAdd("abc1"); dl.myAdd("abc2"); dl.myAdd("abc3"); while (!dl.isNull()){ System.out.println(dl.getLink()); } /* 队列执行结果:abc1 abc2 abc3 -->先进先出 */ DuiZhan dz = new DuiZhan(); dz.myDZadd("abc4"); dz.myDZadd("abc5"); dz.myDZadd("abc6"); while (!dz.dzisNull()){ System.out.println(dz.getDZ()); } /* 堆栈执行结果:abc6 abc5 abc4 -->先进后出 */ } }
2、ArrayList集合
需求:ArrayList里面存放自定义对象
-----Person类-------
package com.JavaStudy01.Bean; /** * @Author wufq * @Date 2020/7/31 11:24 */ public class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public int getAge() { return age; } }
----ArrayList类----
package com.JavaStudy01.ArrayList; import com.JavaStudy01.Bean.Person; import java.util.ArrayList; import java.util.Iterator; /** * @Author wufq * @Date 2020/7/31 11:23 * ArrayList里面存放自定义对象 */ public class ArrayListTest01 { public static void main(String[] args){ ArrayList al = new ArrayList(); al.add(new Person("张三",23)); al.add(new Person("李四",24)); al.add(new Person("王五",25)); Iterator it=al.iterator(); while (it.hasNext()){ Person p= (Person) it.next();//next是一个Object对象,多态强制转换成person对象,用于获取ArrayList里面的元素 System.out.println(p.getName()+"::"+p.getAge()); } } }
ArrayList集合放自定义对象内存原理图
其他知识点:集合里面只能放对象,new ArrayList().add(1); --->其实是进行了自动装箱new ArrayList().add(new integer(1))