文章目录

  • 泛型的引入
  • 实现一个通用的顺序表(直接实践)
    • 准备工作,相信大家都看得懂。
    • 开始掰扯
    • 总结
  • 包装类(Wrapper Class)
    • 基本数据类型和包装类直接的对应关系
    • 包装类存在的意义
      • 实战(讲一个字符串类型转换成整形数据)
    • 包装类的“装箱(boxing) / 装包” 和 “拆箱(unbosxing) / 拆包”
  • ArrayList 与 顺序表
    • 边实践边讲解
      • 实战前的铺垫
    • 在使用任何一个 idea编译器写好的类的时候,一定要先去看一下这个类的构造方法
  • ArrayList的三种打印方式
    • 拓展(迭代器打印)
  • ArrayList基础功能演示
    • add 和 addAll ,添加元素功能
      • 附图
    • remove - 删除 指定下标的元素,返回值为删除元素
      • 附图(remove 内部实现)
    • remove - 输出从左往右 第一个指定数据 - 返回值为布尔类型
      • remove 函数 内部实现 附图
    • get - 换取指定下标位置的元素
      • 附图 (get方法内部)
    • set - 将指定下标元素设置为指定数据(可以理解为更新指定下标元素) - 返回值为旧元素
      • set 内部附图
    • clear - 清空顺序表中的元素 - 无返回值
      • clear 内部实现 附图
    • contains 判断 指定数据 是否在线性表中 - 返回值为布尔类型
      • contains 内部实现 附图
    • indexOf - 返回指定数据在线性表中第一次出现的位置,所对应的下标
      • indexOf 内部实现附图
    • lastIndexOf - 返回 在线性表中,最后一个 与指定元素相等 的 元素下标
      • lastIndexOf 内部实现附图
    • subList - 截取部分 线性表数据 - 返回值 为 List < E > 类型
      • subList 内部实现 附图
  • ArrayList的扩容机制
    • 来看一下,下面的代码是否存在缺陷
    • 下面来跟着我一起 手撕它
  • 模拟实现 ArrayList, 这次的模拟会比上次发的博客[顺序表 和 链表 - 顺序表部分](https://blog.csdn.net/DarkAndGrey/article/details/121125229?spm=1001.2014.3001.5501)更细腻一些。
    • 新建一个 MyArrayList 类,里面我们只需写上最重要的两个属性
    • 然后就是构造方法:带参 和 不带参的 两个构造方法
      • 先来看不带参的
      • 带参的构造方法
    • 接下来怎么写,按照这个表写,实现它的基础功能。(看不懂的,可以翻上去看,前面有实现)
      • add 功能
      • add index 的功能就简单了,因为 支撑它的方法 ,现在几乎都写好了
      • add 两种用法的效果图
      • remove 功能 - 删除删除遇到的第一个 指定元素
      • remove 功能 - 删除 index 位置元素
      • get - 获取指定下标位置元素
      • set - 将指定的下标的元素,置换为 指定的数据
      • clear - 清空
      • contains - 判断 指定元素 是否在线性表中
      • indexOf 和 lastIndexOf ,直接搬原码(注意indexOf 是前面写了的(只要把private改成public就行),直接搬lastIndexOf)
      • 总结:
  • ArrayList 实践案例 - 扑克牌
    • 扑克牌的特点
    • 根据扑克牌的特点,抽象出一个类。
    • 造一张牌
    • 造一副牌
    • 洗牌 -(试问这样的牌,炸金花,谁敢去?谁去谁死。)
    • 发牌 / 揭牌 和 发牌
    • 文章最后,附上扑克牌程序(get 和 set 没用到,可以不用写,我只是习惯性三连)

泛型的引入

泛型在上篇文章集合框架即背后的数据结构中已经降到了,而且用起来了。
再开始之前先要了解两个概念

  1. 首先,我们在学习多态过程中已知一个前提,基类的引用可以指向子类的对象。
  2. 其次,我们也已知 Object 是 java 中所有类的祖先类。

实现一个通用的顺序表(直接实践)

顺序表的功能不是重点,我们在这里只是粗略实现一下顺序表的功能,重点在泛型

准备工作,相信大家都看得懂。

class MyArrayList{private int[] elem;// 建立数组private int usedSize;// 有效元素个数public  MyArrayList(){// 构造方法this.elem = new int[10];// 默认数组初始容量为 10}public void add(int val){// 添加元素this.elem[usedSize] = val;}public int get(int pos){// 得到指定位置的元素return  this.elem[pos];}
}
public class Test {}

但是这个代码并不通用,只能存储一种数据类型(int)。

开始掰扯


再来讨论一下输出

再来掰扯一些细节问题


总结

1. 泛型是作用在编译期间的一种机制,即运行期间没有泛型的概念。
2. 泛型代码在运行期间,就是我们上面提到的,利用 Object 达到的效果(这里不是很准确,以后会做说明)。
3. 泛型是为了解决某些容器、算法等代码的通用性而引入,并且能在编译期间做类型检查。
4. 泛型利用的是 Object 是所有类的祖先类,并且父类的引用可以指向子类对象的特定而工作。
5. 泛型是一种编译期间的机制,即 MyArrayList 和 MyArrayList 在运行期间是一个类型。
6. 泛型是 java 中的一种合法语法,标志就是尖括号 <>


包装类(Wrapper Class)

Object 引用可以指向任意类型的对象,但有例外出现了,8 种基本数据类型不是对象,那岂不是刚才的泛型机制要
失效了?

实际上也确实如此,为了解决这个问题,java 引入了一类特殊的类,即这 8 种基本数据类型的包装类,在使用过程
中,会将类似 int 这样的值包装到一个对象中去。


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

基本就是类型的首字母大写,除了 Integer 和 Character

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

包装类存在的意义

当我们需要将某种类型的数据转换成其它的数据类型时,需要通过某种来达到目的。
而包装类就是这些功能的集大成者,包含多种类型转换方法和其他功能。


实战(讲一个字符串类型转换成整形数据)


包装类的“装箱(boxing) / 装包” 和 “拆箱(unbosxing) / 拆包”

装箱 / 装包 :就是把简单类型数据 变为 包装类类型数据
拆箱 / 拆包 : 就是把包装类类型数据 变为 简单类型数据

借机在这里给大家讲一个面试题


ArrayList 与 顺序表


边实践边讲解

实战前的铺垫


小窗口中显示的是 List接口还实现了那几个接口,或者说是List接口的父类接口

之所以教你们弹出这个框子,是为了方便加下来的讲解,让我们来看看ArrayLis图表

1. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问
2. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的
3. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的(序列化:把一个对象转换成字符串)
4. 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者
CopyOnWriteArrayList
5. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表


在使用任何一个 idea编译器写好的类的时候,一定要先去看一下这个类的构造方法


ArrayList的三种打印方式


可参考顺序表 和 链表 - 顺序表部分来了解ArrayList的常用功能,和 合框架即背后的数据结构了解一下常用接口的基本性质和功能。


拓展(迭代器打印)





ArrayList基础功能演示

add 和 addAll ,添加元素功能

public class TestDemo {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("a");list.add("b");list.add("c");// 添加List元素System.out.println(list);System.out.println("===============");list.add(1,"g");// 在List指定位置中添加元素System.out.println(list);System.out.println("========");List<String> list1 = new ArrayList<>();list1.add("x");list1.add("y");list.addAll(list1);// 将一个list1 整体添加 list中System.out.println(list);}
}

附图


remove - 删除 指定下标的元素,返回值为删除元素

附图(remove 内部实现)


remove - 输出从左往右 第一个指定数据 - 返回值为布尔类型

remove 函数 内部实现 附图


get - 换取指定下标位置的元素

附图 (get方法内部)


取出 elementData 的元素之前,要强转类型。


set - 将指定下标元素设置为指定数据(可以理解为更新指定下标元素) - 返回值为旧元素

set 内部附图


clear - 清空顺序表中的元素 - 无返回值


clear 内部实现 附图


contains 判断 指定数据 是否在线性表中 - 返回值为布尔类型

contains 内部实现 附图


indexOf - 返回指定数据在线性表中第一次出现的位置,所对应的下标


indexOf 内部实现附图



lastIndexOf - 返回 在线性表中,最后一个 与指定元素相等 的 元素下标



lastIndexOf 内部实现附图


subList - 截取部分 线性表数据 - 返回值 为 List < E > 类型

subList 内部实现 附图


ArrayList的扩容机制

来看一下,下面的代码是否存在缺陷

public static void main(String[] args) {List<Integer> list = new ArrayList<>();for (int i = 0; i < 100; i++) {list.add(i);}
}

首先我们认为这个代码是没有缺陷的,但是因为ArrayList 底层的数组是有一定大小的,那么存放数组的过程中,一定会涉及到扩容,
前面我们讲到ArrayList 有三种方法,现在使用的是不带参数的,也就是说ArrayList 底层的数组初始容量为零。 那么第一个问题就出现了: 既然数组的容量是为零,那么它怎么还可以存入数据?
第二个问题: 假设数组初始化容量为10,超过了10,就需要扩容。而且扩容操作时在代码底层执行,是看不见的,也就是说ArrayList在存储数据,隐式的进行扩容操作,那么它的扩容机制是怎样的?


下面来跟着我一起 手撕它


模拟实现 ArrayList, 这次的模拟会比上次发的博客顺序表 和 链表 - 顺序表部分更细腻一些。

新建一个 MyArrayList 类,里面我们只需写上最重要的两个属性


然后就是构造方法:带参 和 不带参的 两个构造方法

先来看不带参的


带参的构造方法


&ensp;

接下来怎么写,按照这个表写,实现它的基础功能。(看不懂的,可以翻上去看,前面有实现)

// E 是数据类型

方法 解释
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,Eelement) 将下标为index的元素,置换为 element
void clear() 清空
boolean contains(Object o) 判断 o 是否在线性表中
int indexOf(Object o) 从左往右 返回第一个 o 的下标
int lastIndexOf(Object o) 返回最后一个o的下标 (从右往左 返回第一个 o 的下标)
List subList(int fromIndex,int tolndex) "截取"部分list

add 功能


&ensp;

add index 的功能就简单了,因为 支撑它的方法 ,现在几乎都写好了


add 两种用法的效果图


remove 功能 - 删除删除遇到的第一个 指定元素


remove 功能 - 删除 index 位置元素


get - 获取指定下标位置元素


set - 将指定的下标的元素,置换为 指定的数据


clear - 清空


contains - 判断 指定元素 是否在线性表中


indexOf 和 lastIndexOf ,直接搬原码(注意indexOf 是前面写了的(只要把private改成public就行),直接搬lastIndexOf)


效果图

总结:

基本功能都实现了,除了subList 没有实现,因为它涉及反射方面的知识,目前还博主还没学到。到后面写到。
另外 你有没有发现。其实你想要模拟顺序表的功能实现,最好的老师就是原码。以后大家在学习某一个数据结构时,先看它的原码,它会帮助你理解并掌握。

其实这次是模拟,只是略微细腻一丢丢,我们还没处理类型转换 和 toString 方法的从写,因为我还有写问题不知道怎么解决,所以我按照自己的想法写了一个,原码的toString还有一些地方,还没理解透。


ArrayList 实践案例 - 扑克牌

目的:
1.构造一副扑克牌
2.揭牌
不包含打牌规则哦~,除非你想让我四。。。


扑克牌的特点


1.点数
2.花色

注意:我们这副扑克,不包含大小王。


根据扑克牌的特点,抽象出一个类。


造一张牌


造一副牌


洗牌 -(试问这样的牌,炸金花,谁敢去?谁去谁死。)


发牌 / 揭牌 和 发牌

假设现在有三个人玩同花顺,也就是说 每个人 手上 会拿到 5 张牌。


文章最后,附上扑克牌程序(get 和 set 没用到,可以不用写,我只是习惯性三连)

import java.util.ArrayList;
import java.util.List;
import java.util.Random;class Card{private int point;private String flowerColor;public Card(int point, String flowerColor) {this.point = point;this.flowerColor = flowerColor;}public int getPoint() {return point;}public void setPoint(int point) {this.point = point;}public String getFlowerColor() {return flowerColor;}public void setFlowerColor(String flowerColor) {this.flowerColor = flowerColor;}@Overridepublic String toString() {return "{  " +flowerColor +" "+point+" }";}
}public class PlayingCard {// 定义 扑克牌的花色private static final String[] flowerColors = {"♥","♠","♦","♣"};// 创建一副扑克public  static List<Card> newCard() {ArrayList<Card> cards = new ArrayList<>();for (int i = 0; i < 4; i++) {// 4种花色for (int j = 1; j <= 13; j++) {// 尖 到 k 一共13个点数cards.add(new Card(j,flowerColors[i]));}}return cards;}// 洗牌public static void shuffle(List<Card> list){// 牌数是52,数组下标就是51// 从最后一张牌开始,随机与 本身 或者 本身前面的任意一张牌 交换位置。// 这样的做交换性 比 从开头洗  的 打乱顺序的 效率 高。for (int i = list.size()-1; i >0 ; i--) {// Random 是一个生成随机数的类Random random = new Random();// 通过 Random的引用 random 去调用 nextInt() 方法。// random.nextInt() 方法,根据括号中的值,随机生成 0 ~ 括号中的值int rand = random.nextInt(i);// 将 第 i 张牌 , 与 自身 或者 自身前面的任意一张牌的下标 丢给 swap方法// 让它去交换位置swap(list,i,rand);}}// 交互式洗牌模式private static void swap(List<Card> list,int i,int j){// 我们现在是面向对象,ArrayList虽然底层是一个数组,但是需要使用方法,才能操作数组的元素// 并不能像数组一样,直接操作// Card tmp = list[i];Card tmp = list.get(i);// 获取 顺序表中,对应下标的元素// list[i] = list[j];list.set(i,list.get(j));// 将 j下标的元素,赋给 i 下标的元素,// list[j] = tmp;list.set(j,tmp);}public static void main(String[] args) {System.out.println("======一副买来拆的牌==========");List<Card> list = newCard();System.out.println(list);System.out.println("======== 洗牌 =========");shuffle(list);System.out.println(list);System.out.println("======== 发牌,3个人轮着发,每个人5张牌=========");ArrayList<ArrayList<Card>> player = new ArrayList<>();// 这行代码 就是 一个二维数组,// 首先我们有一个player, player 的每个元素 都是 ArrayList<Card> 类型。// 也就是说每个元素就是一个顺序表,也可以说是一个一维数组。// 你也可以这么理解 第一个 ArrayList 是用来记录有 玩家的方位/顺序表的地址/数组的地址// 第二个ArrayList 就是 每个玩家手上牌的情况/数组的元素情况/顺序表的底层数组元素情况。//  你可以 把 player 看作牌桌,等待三位玩家的入场。// 打牌三人组ArrayList<Card> playerOne = new ArrayList<>();ArrayList<Card> playerTwo = new ArrayList<>();ArrayList<Card> playerThree = new ArrayList<>();// 将三位玩家的信息,加载到 player 当中player.add(playerOne);player.add(playerTwo);player.add(playerThree);for (int i = 0; i < 5; i++) {// 发 5 轮牌for (int j = 0; j < 3; j++) {// 每个人 轮着发,最终每个人5张牌Card card = list.remove(0);player.get(j).add(card);}}// 打印每个人的手牌System.out.println("playerOne的手牌:"+ playerOne);System.out.println("playerTwo的手牌:"+playerTwo);System.out.println("playerThree的手牌:"+playerThree);System.out.println("list 剩余的牌:"+list);}//    public static void main1(String[] args) {//        Card card = new Card(3,"♠");
//        System.out.println(card);
//    }
}

List 接口相关知识 - ArrayList数据结构 - Java - 细节狂魔(估摸着有几万字)相关推荐

  1. BookCollectionSoftware - 图书管理(知识点糅合::类,对象,抽象类,接口,封装,继承,多态,顺序表)- java - 细节狂魔

    文章目录 前言 图书管理应实现的功能 准备工作 开始操作 先在book包,创建一个Book类,用来存储一本书的信息 小技巧: 根据小技巧来创造我们的 构造方法,公开的输入输出的接口,,还要重写的toS ...

  2. Type-C接口相关知识

    注:内容来自网络,侵删....... Type-C接口详细定义及常用功能 因为Type-C接口比Micro USB有更多的优点,比如,充电时不分正反,随便插:充电时,允许通过的最大电流更大等.现在越来 ...

  3. Camera驱动基础--硬件接口相关知识介绍

    一. LDO, PMIC,PMU, GPIO LDO: 低压差线性稳压器(low dropout regulator): LDO内部有四个部分组成:分别是基准参考电压,误差放大器,分压抽取电路和晶体管 ...

  4. 720phi10p 和 720p有什么区别_HDMI接口有什么用?HDMI接口相关知识详解

    在现如今的电脑当中,高琼的HDMI接口已经逐渐成为了主流视频接口,像VGA模拟接口.DVI数字接口已经逐渐被淘汰掉了.那么HDMI接口怎么样呢?HDMI接口有什么用呢?HDMI接口有几种规格呢?HDM ...

  5. 西米支付:数字藏品支付通道,数字藏品对接支付接口相关知识(供参考)

    自2021年年末开始,数字藏品在我国持续火爆,数藏交易平台的数量已经达到500多家,而且还在以惊人的速度快速增多,剧测算,2026年我国数字藏品市场规模将达300亿元,众多互联网公司纷纷入局. 而构建 ...

  6. Map Set,带你进入Java最常用到的两个接口 - 细节狂魔

    文章目录 搜索 概念及场景 模型 纯 Key 模型 Key - Value模型 Map 的使用 集合框架即背后的数据结构 - 简略概括图 Map 的 说明 Map 的常用方法说明 实践 put 功能 ...

  7. java 接口 抛出异常处理_JAVA中接口与抛出异常的相关知识

    1.接口概念:接口可以理解为一种特殊的类,由全局常量和公共的抽象方法所组成. 类是一种具体实现体,而接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部数据,也不关心这些类里方法的实现细节,它只 ...

  8. Redis 九种数据结构及其底层实现 持久化 缓存机制 过期键与内存淘汰 集群等相关知识

    参考内容: B站尚硅谷Redis视频教程 <Redis 6 入门到精通 超详细 教程> B张黑马程序员Redis视频教程 <黑马程序员Redis入门到实战教程,全面透析redis底层 ...

  9. java的JVM虚拟机相关知识,简单易懂。

    一.    Java class执行方式 1)  概要 Java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次 ...

最新文章

  1. 关于学习Python的一点学习总结(12->字典相关操作)
  2. 大数据架构如何做到流批一体?
  3. LeetCode Algorithm 811. 子域名访问计数
  4. Orchard学习笔记四:启用用户注册
  5. IBASE change and save - Middleware related
  6. spring boot系列 1: 第一个spring boot: Hello prj
  7. Google搜索图片时只显示第一页
  8. 医疗数据典型特征及架构发展方向研究
  9. 【手把手 脑把脑】教会你使用idea基于MapReduce的统计数据分析(从问题分析到代码编写)
  10. C++工作笔记-hiredis中关于ERR wrong number of arguments for HMSET问题的解决
  11. win7计算机记忆窗口,Win7系统关闭和打开搜索记忆功能的方法(图文教程)
  12. NLPCC 2021会议的“面向智能辩论的论辩文本理解”评测比赛综述报告
  13. vecm matlab,VECM是什么?
  14. BIGEMAP地图下载器优势对比(水经注)
  15. 关于AMS1117-ADJ 电压调节计算
  16. 移植Linux Kernel SM750 驱动到VxWorks 7
  17. hone hone clock 与小松鼠驾到~还有牛顿摆等一些其他好玩的东西
  18. 终端服务器安全层在协议流中检测到错误,智能卡远程登录AD域环境下win7/2008,返回STATUS_LOGON_TYPE_NOT_GRANTED错误...
  19. 2022-2028全球与中国立式填模封口机市场现状及未来发展趋势
  20. 2018年就要过去了

热门文章

  1. 电商物流SOP文档的5个注意事项
  2. 海康威视视频监控的实现
  3. IEEE 802.1Q VLAN技术原理
  4. 09 游戏画面管理与切换控制
  5. FFMPEG录屏(13)---- WGC 捕获桌面(一) 改造官网Demo
  6. mirc.7.x-patch by XenoCoder
  7. tspline工具_tsplines 4.0_Autodesk T-Splines 4.0 For Rhino下载 64位免费版 - 121下载站
  8. P1134 [USACO3.2]阶乘问题
  9. 【Win10】联想Z50-70升级到Win10,声音变成环绕声解决办法
  10. vue 项目,下载别人的项目和npm run dev报错解决方法