一、基本介绍:
1、List接口和常用方法
(1)List接口基本介绍:
List接口是Collection接口的子接口
1)List集合类中元素有序(即添加顺序和取出顺序一致),且可重复
2)List集合中每个元素都有其对应的顺序索引,即支持索引(索引从0开始)
3)List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素
4)JDK API中List接口的实现类有
其中常用的有:ArrayList, LinkedList和Vector
·注意:subList()返回的是[fromIndex, toIndex)
5)
//我的代码:
package Collection_;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class List01 {
@SuppressWarnings({"all"})
public static void main(String[] args) {
List list=new ArrayList<>();
list.add("hello");
list.add("hello");
list.add("hello");
list.add("hello");
list.add("hello");
list.add("hello");
list.add("hello");
list.add("hello");
list.add("hello");
list.add("hello");
System.out.println("list="+list);
list.set(2,"韩顺平教育");
System.out.println("list="+list);
System.out.println("list的第5个元素是:"+list.get(5));
list.remove(6);
list.set(7,"hi");
System.out.println("=======使用迭代器遍历list=========");
Iterator iterator=list.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
}
}
//list=[hello, hello, hello, hello, hello, hello, hello, hello, hello, hello]
//list=[hello, hello, 韩顺平教育, hello, hello, hello, hello, hello, hello, hello]
//list的第5个元素是:hello
//=======使用迭代器遍历list=========
//hello
//hello
//韩顺平教育
//hello
//hello
//hello
//hello
//hi
//hello
//老师的代码:
package Collection_;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListExercise01 {
@SuppressWarnings({"all"})
public static void main(String[] args) {
List list=new ArrayList();
for(int i=0;i<12;i++){
list.add("hello"+i);
}
System.out.println("list="+list);
list.add(1,"韩顺平教育");
System.out.println("list="+list);
System.out.println("第五个元素:"+list.get(4));
list.remove(5);
System.out.println("list="+list);
list.set(6,"hi");
System.out.println("list="+list);
Iterator iterator=list.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj="+obj);
}
}
}
//list=[hello0, hello1, hello2, hello3, hello4, hello5, hello6, hello7, hello8, hello9, hello10, hello11]
//list=[hello0, 韩顺平教育, hello1, hello2, hello3, hello4, hello5, hello6, hello7, hello8, hello9, hello10, hello11]
//第五个元素:hello3
//list=[hello0, 韩顺平教育, hello1, hello2, hello3, hello5, hello6, hello7, hello8, hello9, hello10, hello11]
//list=[hello0, 韩顺平教育, hello1, hello2, hello3, hello5, hi, hello7, hello8, hello9, hello10, hello11]
//obj=hello0
//obj=韩顺平教育
//obj=hello1
//obj=hello2
//obj=hello3
//obj=hello5
//obj=hi
//obj=hello7
//obj=hello8
//obj=hello9
//obj=hello10
//obj=hello11
2、List的三种遍历方式:
(1)
package Collection_;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListExercise02 {
@SuppressWarnings({"all"})
public static void main(String[] args) {
List list=new ArrayList();
//List list=new LinkedList();
//List list=new Vector();
list.add(new Book("红楼梦","曹雪芹",100));
list.add(new Book("西游记","吴承恩",10));
list.add(new Book("水浒传","施耐庵",9));
list.add(new Book("三国演义","罗贯中",80));
for (Object o :list) {
System.out.println(o);
}
sort(list);
System.out.println("==================排序后===================");
for (Object o :list) {
System.out.println(o);
}
}
public static void sort(List list){
int listSize=list.size();
for(int i=0;i<listSize-1;i++){
for(int j=0;j<listSize-1-i;j++){
Book book1=(Book) list.get(j);//卡在了如何取出对象Book是关键,使用向下转型
Book book2=(Book) list.get(j+1);
if(book1.getPrice()>book2.getPrice()){
list.set(j,book2);
list.set(j+1,book1);
}
}
}
}
}
class Book{
private String bookName;
private String author;
private double price;
public Book(String bookName, String author, double price) {
this.bookName = bookName;
this.author = author;
this.price = price;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public void bubbleSort(List list){
}
@Override
public String toString() {
return "名称:" + bookName + '\t' + "价格:" + price + '\t' + "作者:" + author;
}
}
//名称:红楼梦 价格:100.0 作者:曹雪芹
//名称:西游记 价格:10.0 作者:吴承恩
//名称:水浒传 价格:9.0 作者:施耐庵
//名称:三国演义 价格:80.0 作者:罗贯中
//==================排序后===================
//名称:水浒传 价格:9.0 作者:施耐庵
//名称:西游记 价格:10.0 作者:吴承恩
//名称:三国演义 价格:80.0 作者:罗贯中
//名称:红楼梦 价格:100.0 作者:曹雪芹
3、ArrayList
(1)注意事项:
1) permits all elements, including null,ArrayList 可以加入null,并且多个
2)ArrayList是由数组来实现数据存储的
3)ArrayList 基本等同于Vector,除了ArrayList是线程不安全(执行效率高)看源码,
在多线程情况下,不建议使用ArrayList
(2)ArrayList的底层操作机制源码分析(重点,难点.)(B站第510集,还没有吃透)
1)ArrayList中维护了一个Object类型的数组elementData.
transient Object[] elementData; //transient表示瞬间、短暂的,表示该属性不会被序列化
2) 当创建对象时,如果使用的是无参构造器,则初始elementData容量为0(jdk7是10)
3) 当添加元素时:先判断是否需要扩容,如果需要扩容,则调用grow方法,否则直接添加元素到合适位置
4) 如果使用的是无参构造器,如果第一次添加,需要扩容的话,则扩容elementData为10,如果需要再次扩容的话,则扩容elementData为1.5倍。
5)如果使用的是指定容量capacity的构造器,则初始elementData容量为capacity
6)如果使用的是指定容量capacity的构造器,如果需要扩容,则直接扩容elementData为1.5倍。
4、Vector:
1) Vector类的定义说明
public class vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
2) Vector底层也是一个对象数组, protected Object[] elementData;
3) Vector 是线程同步的,即线程安全, Vector类的操作方法带有synchronized
public synchronized E get(int index) (
if (index >= elementCount) 1
throw new ArraylndexOutOfBoundsException(index); return elementData(index);
4)在开发中,需要线程同步安全时,考虑使用Vector
5、LinkedList:
(1)基本介绍:
1)LinkedList底层实现了双向链表和双端队列特点
2)可以添加任意元素(元素可以重复),包括null
3)线程不安全,没有实现同步
(2)LinkedList的底层操作机制
1)LinkedList底层维护了一个双向链表.
2)LinkedList中维护了两个属性first和last分别指向 首节点和尾节点
3) 每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点,item用于存放数据。最终实现双向链表.
4)所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。
5) 模拟一个简单的双向链表:
package Collection_;
public class LinkedList_ {
public static void main(String[] args) {
//模拟一个简单的双向链表
Node jack=new Node("jack");
Node tom=new Node("tom");
Node hsp=new Node("老韩");
//连接三个结点,形成双向链表
jack.next=tom;
tom.next=hsp;
//hsp-->tom-->jack
hsp.pre=tom;
tom.pre=jack;
Node first=jack;//让first引用指向jack,就是双向链表的头结点
Node last=hsp;//让last引用指向hsp,就是双向链表的尾结点
System.out.println("=====从头到尾进行遍历======");
while(true){
if(first==null){
break;
}
System.out.println(first);
first=first.next;
}
System.out.println("=====从尾到头进行遍历======");
while(true){
if(last==null){
break;
}
System.out.println(last);
last=last.pre;
}
//添加一个对象,在tom和老韩之间直接插入一个对象smith
Node smith=new Node("smith");
smith.next=hsp;
smith.pre=tom;
hsp.pre=smith;
tom.next=smith;
//让first再次指向jack,就是双向链表的头结点
first=jack;
System.out.println("=====从头到尾进行遍历======");
while(true){
if(first==null){
break;
}
System.out.println(first);
first=first.next;
}
last=hsp;//让last再次指向hsp,就是双向链表的尾结点
System.out.println("=====从尾到头进行遍历======");
while(true){
if(last==null){
break;
}
System.out.println(last);
last=last.pre;
}
}
}
class Node{
public Object item;//真正存放数据
public Node next;//指向后一个结点
public Node pre;//指向前一个结点
public Node(Object name){
this.item=name;
}
@Override
public String toString() {
return "Node name="+item;
}
}
//=====从头到尾进行遍历======
//Node name=jack
//Node name=tom
//Node name=老韩
//=====从尾到头进行遍历======
//Node name=老韩
//Node name=tom
//Node name=jack
//=====从头到尾进行遍历======
//Node name=jack
//Node name=tom
//Node name=smith
//Node name=老韩
//=====从尾到头进行遍历======
//Node name=老韩
//Node name=smith
//Node name=tom
//Node name=jack
补:CRUD:表示增删改查(create, read, update, delete)
6、ArrayList和LinkedList的比较
(2)如何选择ArrayList和LinkedList:
1)如果我们改查的操作多,选择ArrayList
2) 如果我们增删的操作多,选择LinkedList
3) 一般来说,在程序中,80%—90%都是查询,因此大部分情况下会选择ArrayList
4) 在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList,另外一个模块是LinkedList.