零、前言:

一讲到装东西的容器,你可能习惯于使用ArrayList和数组,你有想过ArrayList和数组的区别吗?

Java的类起名字都不是随便乱起的,一般前面是辅助,后面是实质:ArrayList = Array + List

Array就是数组,List便是表结构,ArrayList即数组实现的表结构,问题来了,什么是表结构

注:不要问我效果图用什么软件画的...因为本来就没用什么软件画。下一节带你一起自己画!!!

希望你可以和我在Github一同见证:DS4Android的诞生与成长,欢迎star

0.不管别的,先留图镇楼:

表结构的常规操作

数组的扩容与缩容

1.在我们生活中都有什么表?

课程表,成绩表,作息时间表、列车行程表、手表(这个算了吧...)

复制代码

2.表有什么用?

可以把同类的对象统一管理,比如成绩表:

高三12班的54为同学的成绩是对象,对象又包括数学、语文、英语...等属性

把混乱的54个对象放在一起,这么一排,哪个是学霸,哪个是学渣一目了然,非常方便

如果其中某个对象的成绩改错了,可以get到对象重新set一下,也非常方便

如果中间一个人作弊了,分数取消,直接remove掉,后面的人名词往前排,也非常方便

如果高三12班和高三11班要比较成绩,两张表contact一下,就成一张表,合并也很方便

复制代码

3.表和数组有什么不同?

打个最恰当的比方就是:数组相当于打印出来的纸质版而表结构像是Excel中可操作版

1.数组定长:添加新元素,定位添加都很困难

2.拿删除来说:数组remove掉了,后面的人名次都不变----(我还没个空白名次高,你说气人不气人...)

3.表是一种抽象数据类型(Abstract Data Type),既然是抽象就是规范或功能,表会有不同的实现形式

[番外]:小和尚问老和尚:"什么是圣人?" 老和尚说:"好好学习,天天向上,乐于助人,诚信友善"

这里"圣人"便是一种抽象,"好好学习,天天向上,乐于助人,诚信友善"便是"圣人"的"条件(功能)",

小和尚按照这么做了,他就是老和尚眼中的"圣人",即小和尚实现了圣人。

4.同样,表是一种抽象,也可以定义你眼中的表,并为它附上add(),get(),set(),remove()等功能

5.其实Java的ArrayList实现了List这个抽象接口

复制代码

4.数组表结构:本文要务

一、定义自己的表结构

由于Java用List,为了不混淆,取了个新名字叫Chart

1.定义表的接口

也就是说说你的表能干嘛用(接口方法最好注释非常清晰)

/**

* 作者:张风捷特烈

* 时间:2018/9/25 0025:8:25

* 邮箱:1981462002@qq.com

* 说明:线性表结构接口

*/

public interface IChart {

//region -------------添加操作------------

/**

* 定点添加

*

* @param index 索引

* @param el 数据元素

*/

void add(int index, T el);

/**

* 添加尾

*

* @param el 数据元素

*/

void add(T el);

//endregion

//region -------------删除操作------------

/**

* 定位删除

*

* @param index 索引

* @return 删除的元素

*/

T remove(int index);

/**

* 删除尾位

*

* @return 删除的元素

*/

T remove();

/**

* 删除指定元素的第一次出现时

*

* @param el 数据元素

* @return 元素位置

*/

int removeEl(T el);

/**

* 删除所有指定元素

*

* @param el 数据元素

*/

boolean removeEls(T el);

/**

* 清空集合

*/

void clear();

//endregion

//region -------------改查操作------------

/**

* 设置某位置的元素新值

*

* @param index 索引

* @param el 新值

* @return 旧值

*/

T set(int index, T el);

/**

* 根据指定位置获取元素

*

* @param index 索引

* @return 数据元素

*/

T get(int index);

/**

* 根据指定元素获取匹配索引

*

* @param el 数据元素

* @return 索引集

*/

int[] getIndex(T el);

//endregion

//region ------------其他操作-------------

/**

* 集合是否包含某元素

*

* @param el 数据元素

* @return 是否包含

*/

public boolean contains(T el);

/**

* 连接两个集合

*

* @param iChart 插入集合

* @return 合并后的集合

*/

public IChart contact(IChart iChart);

/**

* 定点连接两个集合

*

* @param index 索引

* @param iChart 插入集合

* @return 合并后的集合

*/

IChart contact(int index, IChart iChart);

/**

* 是否为空

*

* @return 是否为空

*/

boolean isEmpty();

/**

* 返回集合大小

*

* @return 大小

*/

int size();

/**

* 获取数组容量

* @return 数组容量

*/

int capacity();

//endregion

}

复制代码

2.使用数组实现表结构:ArrayChart

实现接口,并实现接口里的所有方法

/**

* 作者:张风捷特烈

* 时间:2018/11/21 0021:8:18

* 邮箱:1981462002@qq.com

* 说明:数组实现线性表结构

*/

public class ArrayChart implements IChart {

//空实现---略

}

复制代码

3.成员变量和构造初始化

private int size;//表中数据的个数

private T[] data;//数据核心承载体

private static final int DEFAULT_CAPACITY = 10;//默认数组容量

private static final float GROW_RATE = 1.5f;//扩容增长率

public ArrayChart() {

this(DEFAULT_CAPACITY);//无参构造默认创建10个容量的数组

}

public ArrayChart(int capacity) {

data = (T[]) new Object[capacity];//新创建[数组表]时初始化数组

}

复制代码

4.简单接口的实现:

@Override

public boolean isEmpty() {

return size == 0;

}

@Override

public int size() {

return size;

}

@Override

public int capacity() {

return data.length;

}

复制代码

二、主要方法的实现(CRUD)

1.定点添加元素:

看一下操作图(将在下一篇:视图篇完成):默认添加到尾部

思路:定点后的所有元素后移一位,空出顶点位,让待添加元素入驻

紫色框代表空的数组位,中间填充的是表中的实际元素

可见定点添加是在选中索引的前一位添加,所以添加到尾部是add(size,data)来添加

@Override

public void add(T el) {

add(size , el);//这里size---是因为在size之前一位添加

}

@Override

public void add(int index, T el) {

if (index < 0 || index > size) {

throw new IllegalArgumentException("Add failed! Make sure index < 0 || index > size");

}

//从最后一个元素开始,到定点位置元素,元素都后移一位

for (int i = size - 1; i >= index; i--) {

data[i + 1] = data[i];

}

data[index] = el;

size++;

}

复制代码

2.查找与设置值:get(),set():

@Override

public T set(int index, T el) {

if (index < 0 || index >= size) {

throw new IllegalArgumentException("Set failed! Make sure index < 0 || index > size");

}

T oldEl = get(index);

data[index] = el;//设置一下,很简单

return oldEl;

}

@Override

public T get(int index) {

if (index < 0 || index >= size) {

throw new IllegalArgumentException("Get failed! Make sure index < 0 || index > size");

}

return data[index];//查询数组的对应索引处

}

复制代码

定值查询获取索引

@Override

public int[] getIndex(T el) {

int[] tempArray = new int[size];//临时数组

int count = 0;//重复个数

for (int i = 0; i < size; i++) {//遍历集合,获取该元素重复个数,及位置数组

if (data[i].equals(el)) {

tempArray[count] = i;

count++;

}

}

//将临时数组压缩---排除空位

int[] indexArray = new int[count];

for (int i = 0; i < count; i++) {

indexArray[i] = tempArray[i];

}

return indexArray;//返回查找元素的索引数组(相当于成绩表看数学80分的都有哪些人)

}

复制代码

3.删除元素:

@Override

public T remove() {

return remove(size - 1);

}

@Override

public T remove(int index) {

if (index < 0 || index >= size) {

throw new IllegalArgumentException("Remove failed! Make sure index < 0 || index > size");

}

T temp = get(index);

//从删除元素索引的下一位开始到结尾,依次左移

// 可简写: System.arraycopy(data, index + 1, data, index + 1 - 1, size - index + 1);

for (int i = index + 1; i < size; i++) {

data[i - 1] = data[i];

}

size--;

//置空--游荡的对象

data[size] = null;

return temp;

}

复制代码

其他删除:

定元素删除单个和定元素删除所有相当于前面的组合操作,就不做操作演示了

@Override

public int removeEl(T el) {

int[] indexes = getIndex(el);//查找元素的索引集合,删除首个

int index = -1;

if (indexes.length > 0) {

index = indexes[0];

remove(indexes[0]);

}

return index;

}

@Override

public boolean removeEls(T el) { //查找元素的索引集合,删除所有

int[] indexArray = getIndex(el);

if (indexArray.length != 0) {

for (int i = 0; i < indexArray.length; i++) {

remove(indexArray[i] - i); // 注意-i

}

return true;

}

return false;

}

复制代码

三、动态扩容与缩容的实现

也没有什么高大上的,就是一个篮子装不下了,装个更大的篮子装而已

1.扩容与缩容方法的实现

/**

* 扩容/缩容

*

* @param newCapacity 新容量

*/

private void grow(int newCapacity) {

T[] newData = (T[]) new Object[newCapacity];//创建个大篮子

for (int i = 0; i < size; i++) {//把原来的元素放到大篮子里

newData[i] = data[i];

}

data = newData;

}

复制代码

2.扩容和缩容的调用契机

什么时候扩容----篮子不够装了呗---add

什么时候需要缩容----1000个容量的篮子装1个鸡蛋想想也浪费---remove

1) add检测扩容时机:满了

@Override

public void add(int index, T el) {

if (size == data.length) {//篮子装不下了---

grow((int) (GROW_RATE * data.length));//换个1.5倍的篮子

}

if (index < 0 || index > size) {

throw new IllegalArgumentException("Add failed! Make sure index < 0 || index > size");

}

//从最后一个元素开始,到定点位置元素,元素都后移一位

//可简写:System.arraycopy(data, index, data, index + 1, size - index);

for (int i = size - 1; i >= index; i--) {

data[i + 1] = data[i];

}

data[index] = el;

size++;

}

复制代码

2)remove检测缩容时机

这里的判断标志是留多点备用,不然有可能插入移除频繁而导致重复扩容或缩容,

篮子可能会说:"你到底缩还是放,你是不是在玩老子....,老子给你多留点空行了吧!"

@Override

public T remove(int index) {

if (index < 0 || index >= size) {

throw new IllegalArgumentException("Remove failed! Make sure index < 0 || index > size");

}

T temp = get(index);

//从删除元素索引的下一位开始到结尾,依次左移

// 可简写: System.arraycopy(data, index + 1, data, index + 1 - 1, size - index + 1);

for (int i = index + 1; i < size; i++) {

data[i - 1] = data[i];

}

size--;

//置空--游荡的对象

data[size] = null;

//缩容----此处限定是为了避免反复出现扩容缩容---可自定义

if (size == data.length / 4 && data.length / 2 != 0 && data.length > 5) {

grow(data.length / 2);

}

return temp;

}

复制代码

3.清空时,数组缩放到初始值

@Override

public void clear() {

size = 0;

grow(DEFAULT_CAPACITY);

}

复制代码

四、其他操作

1.是否包含某元素

@Override

public boolean contains(T el) {

return getIndex(el).length != 0;//按值查询有数据

}

复制代码

2.contact连接数组

@Override

public IChart contact(IChart iChart) {

return contact(size - 1, iChart);

}

@Override

public IChart contact(int index, IChart iChart) {

if (!(iChart instanceof ArrayChart)) {//必须是数组才能联合

return null;

}

//从index处遍历本数组,将待插入数据一个一个插入

for (int i = index; i < index + iChart.size(); i++) {

add(i + 1, iChart.get(i - index));

}

return this;

}

复制代码

作为一个表结构,基本上就演示这么多,还有其他操作可以自定义接口,自己实现,

不过不管多么复杂的操作都是以上操作的组合而已。

五、小结:

关于复杂度的分析,等到所有表结构讲完再整体比较一下,这里先粗略感觉一下

耗时测试

方法\操作次数10001000010W100W1000Wadd首0.0063秒0.2706秒19.5379秒--------

add尾0.0004秒0.0025秒0.0141秒0.0687秒1.26014秒

remove首0.0063秒0.2771秒19.7902秒--------

remove尾0.0005秒0.0036秒0.0091秒0.02301秒:0.1607秒

可以看出往开始添加/删除会很困难,从代码中可以感觉到,毕竟要让后面所有人挪一挪

想一下如果30000人排一起,第一个人走了,后面所有人往前挪一下,是不是工程量挺大的

要是你决定插到第一个,让后面的人都往后移一下.....(大哥,活着难道不好吗....)

所以频繁对第一个元素进行操作的,还是不要作死,数组表结构(ArrayList)不适合你

本系列后续更新链接合集:(动态更新)

后记:捷文规范

1.本文成长记录及勘误表

2.更多关于我

笔名QQ微信爱好张风捷特烈1981462002zdl1994328语言

3.声明

1----本文由张风捷特烈原创,转载请注明

2----欢迎广大编程爱好者共同交流

3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正

4----看到这里,我在此感谢你的喜欢与支持

android 获取数组大小,看得见的数据结构Android版之数组表(数据结构篇)相关推荐

  1. 看得见的数据结构Android版之数组表(数据结构篇)

    零.前言: 一讲到装东西的容器,你可能习惯于使用ArrayList和数组,你有想过ArrayList和数组的区别吗? Java的类起名字都不是随便乱起的,一般前面是辅助,后面是实质:ArrayList ...

  2. 看得见的数据结构Android版之数组表(视图篇)

    零.前言: 1.本文的姊妹篇:看得见的数据结构Android版之表的数组实现(数据结构篇) 2.希望你可以和我在Github一同见证:DS4Android的诞生与成长,欢迎star 3.激动人心的时刻 ...

  3. 看得见的数据结构Android版之表的数组实现(视图篇)

    数据结构-表.png 零.前言: 1.本文的姊妹篇:看得见的数据结构Android版之表的数组实现(数据结构篇) 2.希望你可以和我在Github一同见证:DS4Android的诞生与成长,欢迎sta ...

  4. Android 获取 唯一GUID ,替换 IMEI (兼容 Android 10+获取IMEI问题)

    Android 获取 唯一UUID ,替换 IMEI (兼容 Android 10+获取IMEI问题) 背景 关于 保存GUID方案 第一种,SharedPreferemces存储 第二种,sqlit ...

  5. android 获取视频大小,Android 获取视频缩略图(获取视频每帧数据)的优化方案

    速度对比 左边的图片是通过方式1 右边的图片是通过方式2 speed.gif 速度优化,效果拔群. 在缩小2倍的Bitmap输出情况下 使用MediaMetadataRetriever 抽帧的速度,每 ...

  6. java动态分配数组大小_关于java:如何动态增加2D数组的大小

    如果我知道我有多少个元素,我已经知道如何创建一个固定数组.例如,对于7个元素,我做了一些类似于int数组[2][4]的事情. 但是,如果我在开始时有0个元素(这意味着数组在开始时是空的),并且希望随着 ...

  7. 二维数组大小的确定!你真的是二维数组吗?

    昨天做了一道剑指Offer的题目,是关于dfs的题目,链接点这里 但是其中对于flag[][],二维数组的创建,起了疑惑.在上面链接里也放了关于用new建立二维数组的例子. 但是自己突然想测试一下,用 ...

  8. c语言不允许对数组大小作动态定义,c语言第07章数组.ppt

    第七章,数组,问题:给一组数排序,这组 数该 如何存放呢,??? 这些数据如何存放才便于排序,,1,8,8,8,8,8,8,8,8,8,8,1,,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ...

  9. java动态数组的实现的_Java实现数据结构之【动态数组】

    数组是学习编程语言时较先接触到的一种数据结构,本章基于Java的静态数组实现动态数组,并进行简单的复杂度分析 数组相信各位都知道,那什么是动态数组呢?我们定义一个数组后,一般长度会直接定义好,如果数组 ...

最新文章

  1. 手撸一个JdbcTemplate,带你了解其原理
  2. java多线程 ThreadPoolExecutor 策略的坑
  3. 骑士周游算法 c语言_C语言经典算法04--骑士走棋盘(骑士旅游:Knight tour)
  4. ITK:基于零交叉的边缘检测器
  5. 用Quartus II Timequest Timing Analyzer进行时序分析 :实例讲解
  6. sql server限制查询条数_18. Django 2.1.7 查询集 QuerySet
  7. IDEA入门(一):简介、安装
  8. 拉格朗日乘子法的通俗理解
  9. 已解决 selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element 找不到元素的问题
  10. github生成燃尽图
  11. 编写可维护的JS 04
  12. 不同线程产生的map,会崩溃?
  13. yagmail和keyring的安装与注册
  14. 6个html5手机游戏源码,html5逗你玩手机游戏源码
  15. Web3j使用教程(1)
  16. 《那些年啊,那些事——一个程序员的奋斗史》——36
  17. IFS认证咨询,关于家用和个人护理产品安全和质量的发展和评估项目
  18. chromium45 对应 depot_tools 和 chromium 版本
  19. 制作查询数据窗口php,pb 检索数据窗口做条件查询 | 学步园
  20. msvcp140.dll是什么?怎么修复msvcp140.dll缺失的问题

热门文章

  1. 干货 | 工行分布式数据库选型与大规模容器化实践
  2. STL中算法锦集(三)
  3. 优酷超高清视频技术实践
  4. 京东云端到端多媒体关键技术揭秘
  5. Netflix:通过可视化和统计学改进用户QoE
  6. LiveVideoStackCon讲师热身分享 ( 七 ) —— 视频编码器的对比与选择
  7. 大牛书单 | 搜索大牛都读什么书?
  8. 腾讯发现Google Home首个无接触攻破漏洞
  9. 重磅独家 | 腾讯AI Lab AAAI18现场陈述论文:用随机象限性消极下降算法训练L1范数约束模型
  10. google mock分享