Java中关于泛型、包装类及ArrayList的详细教程

作者:来学习的小张 时间:2021-12-25 00:46:34 

一、泛型

1.1 泛型类的定义


// 1. 尖括号 <> 是泛型的标志
// 2. E 是类型变量(Type Variable),变量名一般要大写
// 3. E 在定义时是形参,代表的意思是 MyArrayList 最终传入的类型,但现在还不知道
public class MyArrayList<E> {
private E[] array;
private int size;
}

泛型类可以一次有多个类型变量,用逗号分割。

  1. 泛型是作用在编译期间的一种机制,即运行期间没有泛型的概念

  2. 泛型代码在运行期间,利用 Object 达到的效果(这里不是很准确)。

  3. 泛型的意义:自动对类型进行检查

1.2 泛型类的使用

示例:


class MyArrayList<E>{//  <E>代表当前类是一个泛型类,此时的E就是一个占位符而已
   private E[] elem;
   private int usedSize;

public MyArrayList() {
//        this.elem = elem;
       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 test02 {
   public static void main(String[] args) {
       //泛型中尖括号里面的内容不参与类型的组成
       MyArrayList<String>  myArrayList = new MyArrayList<>();
       System.out.println(myArrayList);
       MyArrayList<Integer>  myArrayList1 = new MyArrayList<>();
       System.out.println(myArrayList1);
       MyArrayList<Boolean>  myArrayList2 = new MyArrayList<>();
       System.out.println(myArrayList2);
   }
   public static void main2(String[] args) {
       MyArrayList<String>  myArrayList = new MyArrayList<>();
       myArrayList.add("ni");//自动对类型进行检查,不是字符串类型就会报错
       myArrayList.add("n");
       String ret = myArrayList.get(1);//自动对类型进行强制类型转换
       System.out.println(ret);
  }
}

1.3 泛型总结

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

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

  3. 泛型是一种编译期间的机制,即 MyArrayList<Integer>MyArrayList<String> 在运行期间是一个类型。即泛型中尖括号里面的内容不参与类型的组成。

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

二、包装类

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

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

基本就是类型的首字母大写,除了 IntegerCharacter

2.2 包装类的使用,装箱(boxing)和拆箱(unboxing)

装箱(装包):把简单类型变成包装类型。 拆箱(拆包):把包装类型变成简单类型。


public static void main(String[] args) {
       Integer a = 123;//装箱 装包(隐式的)
       //Integer 的范围[-128,127];
       int b= a;//拆箱 拆包(隐式的)
       System.out.println("a="+a+" "+ "b="+ b);
       System.out.println("===============");
       Integer a2 = Integer.valueOf(123);//显式的装包
       Integer a3 = new Integer(123);//显式的装包

int b2 = a2.intValue();//显式的拆包
       double d = a2.doubleValue();//显式的拆包
       int i = 10;//显式的初始化
   }

2.3 自动装箱(autoboxing)和自动拆箱(autounboxing)

在使用过程中,装箱和拆箱带来不少的代码量,所以为了减少开发者的负担,java 提供了自动机制。 自动装箱和自动拆箱是工作在编译期间的一种机制。


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

三、List 的使用

3.1 ArrayList简介

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

Java中关于泛型、包装类及ArrayList的详细教程

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

  • ArrayList实现了Cloneable接口,表明ArrayList是可以clone

  • ArrayList实现了Serializable接口,表明ArrayList支持序列化的

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

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


public static void main(String[] args) {
// ArrayList创建,推荐写法
// 构造一个空的列表
List<Integer> list1 = new ArrayList<>();
// 构造一个具有10个容量的列表
List<Integer> list2 = new ArrayList<>(10);
list2.add(1);
list2.add(2);
list2.add(3);
// list2.add("hello"); // 编译失败,List<Integer>已经限定了,list2中只能存储整形元素
// list3构造好之后,与list2中的元素一致
//使用另外一个ArrayList对list3进行初始化
   ArrayList<String> list3 = new ArrayList<>(list2);
// 避免省略类型,否则:任意类型的元素都可以存放,使用时将是一场灾难
List list4 = new ArrayList();
list4.add("111");
list4.add(100);
}

3.3 ArrayList的遍历

ArrayList 可以使用三种方式遍历:for循环+下标foreach使用迭代器


public static void main(String[] args) {
       List<String> list = new ArrayList<>();
       ArrayList<String> list2 = new ArrayList<>();
       list2.add("hello");
       list2.add("world");
       System.out.println(list2);//打印方式一
       System.out.println("============");
       for (int i = 0; i < list2.size(); i++) {//打印方式二
           System.out.print(list2.get(i)+" ");
       }
       System.out.println();
       System.out.println("==========");
       for (String s:list2) {//打印方式三
           System.out.print(s+" ");
       }
       System.out.println();
       System.out.println("====迭代器打印方式1======");
      Iterator<String> it = list2.iterator();
       while (it.hasNext()){
           System.out.print(it.next()+" ");
       }
       System.out.println();
       System.out.println("=====迭代器打印方式2=====");
       ListIterator<String> it2 = list2.listIterator();//打印方式四,使用迭代器进行打印
       while (it2.hasNext()){
           System.out.print(it2.next()+" ");
       }
   }

输出结果:

Java中关于泛型、包装类及ArrayList的详细教程

3.4 ArrayList的常见操作

3.4.1 删除 index 位置元素(remove)


E remove(int index) //删除 index 位置元素

示例:


public static void main(String[] args) {
       ArrayList<String> list2 = new ArrayList<>();
       list2.add("hello");
       list2.add("bit");
       list2.add("haha");
       Iterator<String> it = list2.iterator();
       while (it.hasNext()) {
           String ret = it.next();
           if(ret.equals("hello")) {
               it.remove();//首先需要使用next方法迭代出集合中的元素 ,然后才能调用remove方法
           }else {
               System.out.print(ret + " ");
           }
       }

System.out.println();
       System.out.println("========迭代器List相关打印==========");
       ListIterator<String> it2 = list2.listIterator();
       while (it2.hasNext()) {
           String ret = it2.next();
           if(ret.equals("hello")) {
               it2.remove();//首先需要使用next方法迭代出集合中的元素 ,然后才能调用remove方法
           }else {
               System.out.print(ret + " ");
           }
       }
   }

输出结果:

Java中关于泛型、包装类及ArrayList的详细教程

3.4.1尾插(add)


boolean add(E e) //尾插 e

示例:


public static void main(String[] args) {
       ArrayList<String> list2 = new ArrayList<>();
       //CopyOnWriteArrayList<String> list2 = new CopyOnWriteArrayList<>();
       list2.add("hello");
       list2.add("bit");
       list2.add("haha");

//Iterator迭代器没有add方法
      /* Iterator<String> it = list2.iterator();
       while (it.hasNext()) {
           String ret = it.next();
           if(ret.equals("hello")) {
               it.add();//没有add方法
           }else {
               System.out.print(ret + " ");
           }
       }*/

//使用ListIterator迭代器的方法添加元素,会将元素添加到其紧跟着的后面
       ListIterator<String> it2 = list2.listIterator();
       while (it2.hasNext()) {
           String ret = it2.next();
           if(ret.equals("bit")) {
               it2.add("world");
          //若使用list2.add()就会抛出异常,
          //但是将上面的list2变成CopyOnWriteArrayList<String>类型就不会报错。
           //就可以使用list2.add()的方法就可以
          // list2.add("world");
           }else {
               System.out.print(ret + " ");
           }
       }
       System.out.println("=================");
       System.out.println(list2);
   }

运行结果:

Java中关于泛型、包装类及ArrayList的详细教程


 ArrayList<String> list2 = new ArrayList<>();//不是线程安全的
 迭代时使用的是it2.add("world");
CopyOnWriteArrayList<String> list2 = new CopyOnWriteArrayList<>();//是线程安全的
 迭代时使用的是list2.add("world");

3.4.2将元素插入到list中的指定位置add

3.4.3 尾插一个ArrayList中的所有元素到另一个ArrayList当中(addAll)

方法:


void add(int index, E element) //将 e 插入到 index 位置
boolean addAll(Collection<? extends E> c) //尾插 c 中的元素

示例:


public static void main(String[] args) {
       ArrayList<String> list2 = new ArrayList<>();
       list2.add("a");
       list2.add("b");
       list2.add("c");
       list2.add("d");
       list2.add("d");
       System.out.println(list2);//add方法默认将字符串放到数组的最后一个位置
       list2.add(0,"hello");//在list2的零下标位置加入字符串"hello"
       System.out.println(list2);
       ArrayList<String> list3 = new ArrayList<>();
       list3.add("加入");
       list2.addAll(list3);//将list3中的所有元素放到list2中
       System.out.println(list2);
   }

输出结果:

Java中关于泛型、包装类及ArrayList的详细教程

3.4.4 删除指定下标位置的元素remove(int index)

3.4.5删除list中第一次出现的某元素remove(Object o)

3.4.6 获取某下标位置的元素get()

3.4.7 将指定下标位置的元素设置为指定值set()

方法:


E remove(int index) //删除 index 位置元素
boolean remove(Object o) //删除遇到的第一个 o
E get(int index) //获取下标 index 位置元素
E set(int index, E element) //将下标 index 位置元素设置为 element

示例:


public static void main(String[] args) {
       ArrayList<String> list2 = new ArrayList<>();
       list2.add("a");
       list2.add("b");
       list2.add("c");
       list2.add("d");
       list2.add("d");
       System.out.println(list2);//add方法默认放到数组的最后一个位置
        String ret = list2.remove(0);//删除0下标位置元素
       System.out.println(list2);

boolean ret1 = list2.remove("d"); //删除遇到的第一个"d"
       //如果要删除的数list2中没有则返回false
       System.out.println(ret1); //true
       String ret2 = list2.get(2);//获取下标为2位置的元素
       System.out.println(ret2);//d
       String ret3 = list2.set(2,"hello");//将下标为2位置的元素改为"hello"
       System.out.println(ret3);//d
       System.out.println(list2);//[b, c, hello]

输出结果:

Java中关于泛型、包装类及ArrayList的详细教程

3.4.8 清空线性表中的元素clear()

3.4.9 判断线性表中是否包含某元素 contains()

3.4.10 返回第一个 o 所在下标位置 indexOf()

3.4.11 返回最后一个o出现的下标位置 lastIndexOf()

3.4.12 截取部分 list 中的部分元素 subList()

方法:


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

示例:


public static void main(String[] args) {
       ArrayList<String> list2 = new ArrayList<>();
       list2.add("a");
       list2.add("b");
       list2.add("c");
       list2.add("d");
       list2.add("d");
       System.out.println(list2);//add方法默认放到数组的最后一个位置
       System.out.println(list2.indexOf("a"));//0 判断a的下标位置
       System.out.println(list2.lastIndexOf("d"));//4 判断最后一个d出现的下标位置
       List<String> sub = list2.subList(1,3);//[b, c] 截取下标为[1,3)位置的元素,截取的区间范围为左闭右开的
       System.out.println(sub);//[b, c]
       System.out.println(list2);//[a, b, c, d, d]
       System.out.println("===================");
       sub.set(0,"p");
       System.out.println(sub);//[p, c]
       System.out.println(list2);//[a, p, c, d, d]
      System.out.println(list2.contains("c"));//true //判断list2当中是否包含字符"c"
       list2.clear();//将list2中的元素清空
       System.out.println(list2);

输出结果:

Java中关于泛型、包装类及ArrayList的详细教程

四、ArrayList的扩容机制

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

来源:https://blog.csdn.net/dddddrrrzz/article/details/121691217

标签:java,泛型,包装类,ArrayList
0
投稿

猜你喜欢

  • C# [ImportDll()] 知识小结

    2022-09-15 07:42:18
  • Spring如何使用xml创建bean对象

    2023-10-24 08:53:56
  • C#基于正则表达式删除字符串中数字或非数字的方法

    2021-07-12 17:27:44
  • 解决运行jar包出错:ClassNotFoundException问题

    2021-09-09 04:58:41
  • flutter中的资源和图片加载示例详解

    2023-08-24 13:19:39
  • Android使用系统相机进行拍照的步骤

    2023-10-07 16:05:05
  • SpringSceurity实现短信验证码登陆

    2023-06-23 00:37:35
  • windows下java环境变量的设置方法

    2022-12-01 03:13:14
  • C#中decimal保留2位有效小数的实现方法

    2023-01-30 07:35:13
  • java实现微信红包 拼手气红包

    2023-09-28 10:31:45
  • c#数据绑定之linq使用示例

    2022-07-17 11:07:22
  • 使用idea解决maven依赖冲突的问题

    2021-10-16 12:32:51
  • java开发微信分享接口的步骤

    2021-08-22 12:30:59
  • 学习Android自定义Spinner适配器

    2022-12-15 01:28:31
  • mybatis注入Date日期值为null的解决方法

    2021-12-08 01:49:17
  • 解决idea打包成功但是resource下的文件没有成功的问题

    2023-10-11 06:21:12
  • Java spring AOP基础

    2022-08-10 12:39:25
  • 关于springboot2.4跨域配置问题

    2022-05-01 17:02:15
  • 对Mapper 中几种update的区别说明

    2023-05-19 04:39:44
  • IDEA中java断言assert语法及使用

    2022-12-28 21:07:00
  • asp之家 软件编程 m.aspxhome.com