Java学习苦旅(十六)——List

本篇博客将详细讲解Java中的List。

文章目录

预备知识------初识泛型

泛型的引入

我们之前实现过的顺序表,只能保存int类型的元素,如果现在需要保存指向String类型对象的引用的顺序表,请问应该如何解决?

这个时候就需要引入泛型这个概念了。

泛型的意义:

  • 自动对类型进行检查
  • 自动对类型进行强制类型的转换

示例代码:

java 复制代码
class MyArrayList<E> {
    private E[] elem;
    private int usedSize;
    
    public MyArrayList() {
        this.elem = (E[]) new Object[10];
    }

    public void add(E val) {
        this.elem[usedSize] = val;
        usedSize++;
    }

    public E get(int pos) {
        return this.elem[pos];
    }
}

public class TestDemo {
    public static void main(String[] args) {
        MyArrayList<String> myArrayList = new MyArrayList<>();
        myArrayList.add("ABC");
        myArrayList.add("DEF");
        System.out.println(myArrayList.get(1));
    }
}

执行结果为:

泛型小结

  1. 泛型是为了解决某些容器、算法等代码的通用性而引入,并且能在编译期间做类型检查。

  2. 泛型利用的是 Object 是所有类的祖先类,并且父类的引用可以指向子类对象的特定而工作。

  3. 泛型是一种编译期间的机制,即 MyArrayList<Integer> 和MyArrayList<String> 在运行期间是一个类型。

  4. 泛型是 java 中的一种合法语法,标志就是尖括号<>。

预备知识------包装类

基本数据类型和包装类直接对应关系

基本数据类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

装包与拆包

示例代码

java 复制代码
Integer a = 123;//隐式的装包
int b = a;//隐式的拆包

Integer a2 = Integer.valueOf(123);//显式的装包
Integer a3 = new Integer(123);//显式的装包

int b2 = a2.intValue();//显式的拆包

ArrayList

简介

在集合框架中,ArrayList是一个普通的类,实现了List接口,具体框架图如下:

说明

  1. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问。

  2. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的。

  3. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的。

  4. 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者CopyOnWriteArrayList。

  5. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表。

ArrayList使用

ArrayList的构造

方法 解释
ArrayList() 无参构造
ArrayList(Collection<? extends E> c) 利用其他Collection构建ArrayList
ArrayList(int initialCapacity) 指定顺序表初始容量

示例代码

java 复制代码
public static void main(String[] args) {
    List<Integer> list1 = new ArrayList<>();//构造一个空的列表

    List<Integer> list2 = new ArrayList<>(10);//构造一个具有10个容量的列表
    list2.add(1);
    list2.add(2);
    list2.add(3);

    ArrayList<Integer> list3 = new ArrayList<>(list2);//list3构造好之后,与list2中的元素一致
}

结论:

如果ArrayList调用,不带参数的构造方法,那么顺序表的大小是0。当第一次add的时候,整个顺序表才变为了10,当这10个放满了,开始扩容,以1.5倍的方式进行扩容。

如果调用的是给定容量的构造方法,那么顺序表的大小是所给的容量,放满之后还是以1.5倍进行扩容。

ArrayList常见操作

方法 解释
boolean add(E e) 尾插e
void add(int index, E element) 将e插入到index位置
boolean addAll(Collection<? extends E> c) 尾插c中的元素
E remove(int index) 删除index位置元素
boolean remove(Object o) 删除遇到的第一个o
E get(int index) 获取下标index位置元素
E set(int index, E element) 将下标index位置元素设置为element
void clear() 清空
boolean contains(Object o) 判断o是否在线性表中
int indexOf(Object o) 返回第一个o所在下标
int lastIndexOf(Object o) 返回最后一个o的下标
List<E> subList(int fromIndex, int toIndex) 截取部分list

示例代码

java 复制代码
List<String> list = new ArrayList<>();
list.add("abc");
list.add("def");
list.add("ABC");
list.add("EFG");
System.out.println(list);
System.out.println(list.size());//获取list中有效元素个数
System.out.println("=========更改指定元素==========");
System.out.println(list.get(1));
list.set(1,"xyz");
System.out.println(list.get(1));
System.out.println("=========插入指定元素==========");
list.add(1,"LMN");//在list的index位置插入指定元素,index及后续的元素统一往后移动一个位置
System.out.println(list);
System.out.println("=========删除指定元素==========");
list.remove("ABC");//删除指定元素,找到了就删除,该元素之后的元素统一往前移动一个位置
System.out.println(list);
if(list.contains("OPQ")) {
    list.add("OPQ");
}
System.out.println("===查找指定元素第一次出现的位置===");
System.out.println(list.indexOf("EFG"));//indexOf从前往后找
System.out.println(list.lastIndexOf("EFG"));//lastIndexOf从后往前找
System.out.println("============================");
List<String> ret = list.subList(1,3);
System.out.println(ret);

list.clear();
System.out.println(list.size());

执行结果为:

ArrayList遍历

示例代码

java 复制代码
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
//直接打印
System.out.println(list);
//使用for循环
for (int i = 0; i < list.size(); i++) {
    System.out.print(list.get(i) + " ");
}
System.out.println();
//使用for-each
for (Integer s : list) {
    System.out.print(s + " ");
}
System.out.println();
//迭代器打印------Iterator
Iterator<Integer> it = list.iterator();
while(it.hasNext()) {
    System.out.print(it.next() + " ");
}
System.out.println();
//迭代器打印------ListIterator
ListIterator<Integer> it1 = list.listIterator();
while(it1.hasNext()) {
    System.out.print(it1.next() + " ");
}
System.out.println();

执行结果为:

结尾

本篇博客到此结束。

上一篇博客:Java学习苦旅(十五)------异常

下一篇博客:Java学习苦旅(十七)------栈和队列

相关推荐
艾迪的技术之路几秒前
redisson使用lock导致死锁问题
java·后端·面试
今天背单词了吗98019 分钟前
算法学习笔记:8.Bellman-Ford 算法——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·开发语言·后端·算法·最短路径问题
天天摸鱼的java工程师21 分钟前
使用 Spring Boot 整合高德地图实现路线规划功能
java·后端
东阳马生架构37 分钟前
订单初版—2.生单链路中的技术问题说明文档
java
咖啡啡不加糖1 小时前
暴力破解漏洞与命令执行漏洞
java·后端·web安全
风象南1 小时前
SpringBoot敏感配置项加密与解密实战
java·spring boot·后端
DKPT1 小时前
Java享元模式实现方式与应用场景分析
java·笔记·学习·设计模式·享元模式
Percep_gan1 小时前
idea的使用小技巧,个人向
java·ide·intellij-idea
缘来是庄1 小时前
设计模式之迭代器模式
java·设计模式·迭代器模式