0515项目优化和List集合
0515项目优化和List集合
1. 项目优化
1.1 分析当前情况
问题
数据存储是数组形式,数据类型明确。复用度较低。
需求
Student操作使用的代码,StudentManager想要操作考虑一个复用度问题。不管更换什么数据类型, 都是可以直接使用。
解决问题
1. 泛型
2. 数组不能使用泛型,但是这个数组又需要保存各式各样的数据
Object
1.2 使用泛型和Object优化项目
package com.qfedu.student.system.util;
import com.qfedu.student.system.myexception.IllegalCapacityException;
import com.qfedu.student.system.myexception.OverflowMaxArraySizeException;
/**
* 自定义数据存储工具,MyList用于存储代码中操作的数据
*
* @author Anonymous
*
* @param <E> 使用泛型满足更多的情况
*/
public class MyList<E> {
/**
* 保存数据的底层Object数组,可以保存任意数据类型,但是在操作方法是会
* 对操作的数据类型,通过泛型进行约束操作
*/
private Object[] elementData = null;
/**
* DEFAULT_CAPACITY 默认容量,这里是一个带有名字的常量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 数组最大容量,是int类型最大值 - 8 -8等我给你讲
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* 当前底层Object数组中有效元素个数
*/
private int size = 0;
/**
* 无参数构造方法,使用DEFAULT_CAPACITY约束初始化容量
*/
public MyList() {
elementData = new Object[DEFAULT_CAPACITY];
}
/**
* 提供给用户可以指定初始化容量的操作方法
*
* @param initCapacity 用户指定的初始化容量,但是必须在合理范围以内
* @throws IllegalCapacityException 用户指定的初始化容量超出范围
*/
public MyList(int initCapacity) throws IllegalCapacityException {
if (initCapacity < 0 || initCapacity > MAX_ARRAY_SIZE) {
throw new IllegalCapacityException("Input Parameter is Invalid!");
}
elementData = new Object[initCapacity];
}
/**
* 添加方法,添加在创建MyList对象是约束的具体数据类型
*
* @param e 通过泛型约束的具体数据类型
* @return 添加成功返回true, 否则返回false
* @throws OverflowMaxArraySizeException
*/
public boolean add(E e) throws OverflowMaxArraySizeException {
if (size == elementData.length) {
// 添加操作是一个元素,最小容量要求就是在原本的数组容量之上 + 1
grow(size + 1);
}
elementData[size] = e;
size += 1;
return true;
}
/**
* 删除保存在MyList中的指定元素
*
* @param obj 用户指定的元素
* @return 删除成功返回true,否则返回false
*/
public boolean remove(Object obj) {
int index = indexOf(obj);
return remove(index);
}
/**
* 删除指定下标的的元素
*
* @param index 用户指定的下标位置
* @return 删除成功返回true,否则返回false
*/
public boolean remove(int index) {
if (index < 0 || index >= size) {
return false;
}
for (int i = index; i < size - 1; i++) {
elementData[i] = elementData[i + 1];
}
// 原本最后一个有效元素位置赋值为null
elementData[size - 1] = null;
// 有效元素个数 - 1
size -= 1;
return true;
}
/**
* 根据指定元素,找出对应的下标位置,没有找到返回-1
*
* @param obj 用户传入的元素
* @return 找到元素返回值大于等于0,没有找到返回-1
*/
public int indexOf(Object obj) {
int index = -1;
for (int i = 0; i < size; i++) {
if (obj.equals(elementData[i])) {
index = i;
break;
}
}
return index;
}
/**
* 替换修改方法,使用指定元素替换指定下标的元素
*
* @param index 指定的下标位置,约束在合理范围以内
* @param e 泛型约束的指定数据类型,保证数据类型一致化
* @return 被替换掉的元素。如果没有被替换的元素,返回null
*/
public E set(int index, E e) {
if (index < 0 || index >= size) {
return null;
}
// 取出原本的元素
E temp = (E) elementData[index];
elementData[index] = e;
return temp;
}
/**
* 返回当前MyList底层数组中保存有效元素个数是多少个
*
* @return 返回当前MyList底层数组中有效元素个数
*/
public int size() {
return size;
}
/**
* 判断当前MyList中是否为空
*
* @return 如果是空返回true,否则返回false
*/
public boolean isEmpty() {
return 0 == size;
}
/**
* 判断指定元素是否在MyList底层数组中存在
*
* @param obj 用户指定的元素
* @return 存在返回true,不存在返回false
*/
public boolean contains(Object obj) {
return indexOf(obj) > -1;
}
/**
* 根据指定下标位置,获取对应的元素
*
* @param index 指定下标位置
* @return 对应的元素,如果不存在,返回null
*/
public E get(int index) {
return index > -1 && index < size ? (E) elementData[index] : null;
}
/**
* 类内私有化方法,用于在添加元素过程中,出现当前底层数组容量不足的情况下 对底层数组进行扩容操作,满足使用要求
*
* @param minCapacity 添加操作要求的最小容量
* @throws OverflowMaxArraySizeException 数组容量超出最大范围
*/
private void grow(int minCapacity) throws OverflowMaxArraySizeException {
// 1. 获取原数组容量
int oldCapacity = elementData.length;
// 2. 计算得到新数组容量,新数组容量大约是原数组容量的1.5倍
// >> 1 右移一位 该操作是二进制操作 等价于 / 2 效率略高
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 3. 判断新数组容量是否满足最小容量要求
if (minCapacity > newCapacity) {
newCapacity = minCapacity;
}
// 4. 判断当前容量是否超出了MAX_ARRAY_SIZE
if (newCapacity > MAX_ARRAY_SIZE) {
throw new OverflowMaxArraySizeException("Overflow MAX_ARRAY_SIZE");
}
// 5. 创建新数组
Object[] temp = new Object[newCapacity];
// 6. 数据拷贝
for (int i = 0; i < oldCapacity; i++) {
temp[i] = elementData[i];
}
// 7. 使用allStus保存新数组首地址
elementData = temp;
}
}
2. List接口
2.1 List接口概述
List接口特征:
1. 数据存储可重复。
2. 有序,添加顺序和保存顺序一致。
--| ArrayList<E>
可变长数组
--| LinkedList<E>
双向链表
--| Vector<E>
线程安全的可变长数组
2.2 List常用方法
增
boolean add(E e);
List接口继承Collection接口 add方法,使用操作和Collection一致,并且这
里采用的添加方式是【尾插法】
boolean add(int index, E e);
List接口【特有方法】,在指定位置,添加指定元素。
boolean addAll(Collection<? extends E> c);
List接口继承Collection接口 addAll方法,使用操作和Collection一致,并
且这里采用的添加方式是【尾插法】
boolean addAll(int index, Collection<? extends E> c);
List接口【特有方法】,在指定下标位置,添加另一个集合中所有内容
删
E remove(int index);
List接口【特有方法】,获取指定下标位置的元素。
boolean remove(Object obj);
List接口继承Collection接口方法。删除集合中的指定元素
boolean removeAll(Collection<?> c);
List接口继承Collection接口方法。删除当前集合中和参数集合重复元素
boolean retainAll(Collection<?> c);
List接口继承Collection接口方法。保留当前集合中和参数集合重复元素
clear();
List接口继承Collection接口方法。清空整个集合中的所有元素
改
E set(int index, E e);
List接口【特有方法】,使用指定元素替代指定下标的元素,返回值是被替换的元
素
查
int size();
List接口继承Collection接口方法。获取集合中有效元素个数
boolean isEmpty();
List接口继承Collection接口方法。判断当前集合是否为空
boolean contains(Object obj);
List接口继承Collection接口方法。判断指定元素是否包含在当前集合中
boolean containsAll(Collection<?> c);
List接口继承Collection接口方法。判断参数集合是不是当前集合在子集合
Object[] toArray();
List接口继承Collection接口方法。获取当前集合中所有元素Object数组
E get(int index);
List接口【特有方法】。获取指定下标对应的元素
List<E> subList(int fromIndex, int toIndex);
List接口【特有方法】。获取当前集合指定子集合,从fromIndex开始,到
toIndex结束。fromIndex <= 范围 < toIndex
int indexOf(Object obj);
List接口【特有方法】。获取指定元素在集合中第一次出现位置
int lastIndexOf(Object obj);
List接口【特有方法】。获取指定元素在集合中最后一次出现的位置
2.3 List接口常用方法演示
package com.qfedu.a_list;
import java.util.ArrayList;
import java.util.List;
public class Demo1 {
public static void main(String[] args) {
/*
* List<E>是一个接口,没有自己的类对象,这里使用List接口的
* 实现类ArrayList来演示代码。
*/
List<String> list = new ArrayList<String>();
/*
* 添加方法演示
*/
list.add("浓郁咖啡摩卡");
list.add("浓郁咖啡拿铁");
list.add("焦糖玛奇朵");
list.add("摩卡可可碎星冰乐");
list.add("可可卡布奇诺");
System.out.println(list);
list.add(3, "美式咖啡");
System.out.println(list);
List<String> list2 = new ArrayList<String>();
list2.add("肥宅快乐水");
list2.add("芬达");
list2.add("雪碧");
list2.add("冰峰");
list.addAll(4, list2);
System.out.println(list);
/*
* 删除方法
*/
String remove = list.remove(1);
System.out.println(remove);
System.out.println(list);
// 条件过滤,这里使用了JDK1.8 新特征 Lambda表达式和函数式接口 【后期知识点】
list.removeIf((str) -> str.length() > 4);
System.out.println(list);
}
}
package com.qfedu.a_list;
import java.util.ArrayList;
import java.util.List;
public class Demo1 {
public static void main(String[] args) {
/*
* List<E>是一个接口,没有自己的类对象,这里使用List接口的
* 实现类ArrayList来演示代码。
*/
List<String> list = new ArrayList<String>();
/*
* 添加方法演示
*/
list.add("浓郁咖啡摩卡");
list.add("浓郁咖啡拿铁");
list.add("焦糖玛奇朵");
list.add("摩卡可可碎星冰乐");
list.add("可可卡布奇诺");
System.out.println(list);
list.add(3, "美式咖啡");
System.out.println(list);
List<String> list2 = new ArrayList<String>();
list2.add("肥宅快乐水");
list2.add("芬达");
list2.add("雪碧");
list2.add("冰峰");
list.addAll(4, list2);
System.out.println(list);
/*
* 删除方法
*/
String remove = list.remove(1);
System.out.println(remove);
System.out.println(list);
// 条件过滤,这里使用了JDK1.8 新特征 Lambda表达式和函数式接口 【后期知识点】
list.removeIf((str) -> str.length() > 4);
System.out.println(list);
}
}
阿里巴巴笔试题
1.已知有20个String对象,请将他们插入ArrayList
2.int[1,2,3,4,5] 转换成Integer[]
3. ArrayList【重点】
3.1 ArrayList概述
ArrayList是在Java中集合非常重要的一个组装,基于数组完成的数据结构。可变长数组操作!!!
底层保存数据的是一个Object类型数组。
ArrayList使用的方法都是List接口中的方法,有两个需要了解的成员方法:
ensureCapacity();
判断方法,用于确定当前底层数组的容量是否满足当前操作的需求。
trimToSize();
节省空间,将底层数组的容量缩容至有效元素个数
需要掌握的是关于ArrayList效率相关的问题。和细节问题
3.2 细节问题
1. DEFAULT_CAPACITY
默认容量 private static final int DEFAULT_CAPACITY = 10;
在调用ArrayList无参数构造方法是,才会使用DEFAULT_CAPACITY,作为底层Object数组的初始化容量。如果用户指定调用的是带有初始化底层Object数组容量的构造方法,会根据用户指定的容量创建对一个ArrayList集合。】
2. MAX_ARRAY_SIZE ==> Integer.MAX_VALUE - 8;
int[] arr = new int[10];
arr.length 是什么??? 数组容量
这里是一个方法还是属性??? 属性
属性是不是成员变量??? 是
成员变量是否需要占用内存??? 需要
new数组占用的空间什么地方??? 堆区
arr.length 属性是不是也在堆区??? 是
为什么 - 8???
因为在数组中存在很多属性,length只是众多属性中的一个,在创建数组使用的过
程中,需要留有内存空间用于保存数组中属性。
我买的房子
109.32
公摊 之后 87.22
套内面积是实际使用面积 69
3.3 效率问题
ArrayList特征:
增删慢
增加慢
1. 数组当前容量无法满足添加操作,需要进行grow扩容方法执行,在扩容方
法中,存在数组创建,数组数据拷贝。非常浪费时间,而且浪费内存。
2. 数组在添加数据的过程中,存在在指定位置添加元素,从指定位置开始,
之后的元素整体向后移动。
删除慢
1. 删除数据之后,从删除位置开始,之后的元素整体向前移动,移动过程非
常浪费时间
2. 删除操作会导致数据空间的浪费,内存的浪费
查询快
ArrayList底层是一个数组结构,在查询操作的过程中,是按照数组+下标的方式
来操作对应的元素,数组+下标方式可以直接获取对应的空间首地址,CPU访问效率
极高。
3.4 【补充知识点,内存地址】
内存地址概念:
[计算机原理]
计算机中为了更好的使用内存,操作程序,完成代码。将内存按照最小单位,进行编号处理。
最小单位: 字节 byte
从编号为0内存开始,到内存的最大值。地址的展示方式是十六进制。
生活案例。
郑州银屏路115号
航海中路60号 这些编号有木有唯一性???
这些编号具有唯一性,精确定位,精确指向!!!
在软件开发中就是采用类似于生活中小区,工厂编号模式,在一条路中对每一个单位进行编号处理。
以32G内存为例
0x0 ~ 0x7 FFFF FFFF
3.5 【补充知识点 内存地址对于CPU有什么关系】
生活案例:
快递小哥,可以根据地址直接高效送快递到你家。根据地址来处理快递。
航海中路60号,这是唯一地址!!!
快递小哥我们可以看做是CPU,快递上地址,就是内存地址,具有唯一性!!!
代码实际运行:
CPU就是根据内存地址,可以直达内存所在区域,执行对应代码。精准而优雅,速度非常快!!!
3.6 【补充知识点 数组空间地址关系】
3.7【补充知识点 null到底是什么】
null 是计算机中非常特殊的一块内存。该内存编号 0x0000 0000
该内存受到系统保护
不只是电脑,包括手机,iPad,智能设备,只要存在计算机基本结构的设备上都存在null 编号为0x0内存。大小一个字节
该内存不能读取任何数据,也不能写入任何数据。一旦操作,程序直接被系统杀死
Kill -9
一般用于引用数据类型的初始化,利用开发中关于null的异常,辅助找出代码中的错误。
NullPointerException.
0515项目优化和List集合的更多相关文章
- 【C#】项目优化实战
[C#]项目优化实战 一. 数据库设计 1. 常量的枚举值直接存中文不要存数字(注意是常量,如果显示值可变就不能) 例如:男女,在数据库中不要存1和0,直接存男和女. 这样的好处:读取数据的时候可以避 ...
- 项目优化经验分享(八)TeamLeader经验总结
引言 通过前面的七篇博客.我把自己在项目优化过程的经验进行了分享,今天这篇博客,作为一个总结,就来讲讲作为一个TeamLeader,在项目管理中遇到的问题和解决经验! 正文 问题一:团队之间怎么沟通? ...
- 深入浅出聊Unity3D项目优化:从Draw Calls到GC
前言: 刚开始写这篇文章的时候选了一个很土的题目...<Unity3D优化全解析>.因为这是一篇临时起意才写的文章,而且陈述的都是既有的事实,因而给自己“文(dou)学(bi)”加工留下的 ...
- Unity3D项目优化(转)
前言: 刚开始写这篇文章的时候选了一个很土的题目...<Unity3D优化全解析>.因为这是一篇临时起意才写的文章,而且陈述的都是既有的事实,因而给自己“文(dou)学(bi)”加工留下的 ...
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(十四)谈谈写博客的原因和项目优化
阶段总结 又到了优化篇的收尾阶段了,这其实是一篇阶段总结性的文章,今天是4月29号,距离第一次发布博客已经两个月零5天,这两个多月的时间,完成了第一个项目ssm-demo的更新,过程中也写了33篇博客 ...
- vue-cli 项目优化之3种方法对比:本地静态库资源(推荐)、cdn、DllPlugin
vue-cli 项目优化之3种方法对比:本地静态库资源(推荐).cdn.DllPlugin 事项 本地静态库资源 cdn DllPlugin 依赖 依赖cdn网站资源(有种完善方法:如果cdn引入不成 ...
- vue单页面应用项目优化总结(转载)
转载自:https://blog.csdn.net/qq_42221334/article/details/81907901这是之前在公司oa项目优化时罗列的优化点,基本都已经完成,当时花了点心思整理 ...
- 大型vue单页面项目优化总结
这是之前在公司oa项目优化时罗列的优化点,基本都已经完成,当时花了点心思整理的,保存在这里,方便以后其他项目用到查漏补缺. 1.打包文件中的app.js文件放入cdn,加快页面首次加载速度 2.提取公 ...
- 前端项目优化 -Web 开发常用优化方案、Vue & React 项目优化
github github-myBlob 从输入URL到页面加载完成的整个过程 首先做 DNS 查询,如果这一步做了智能 DNS 解析的话,会提供访问速度最快的 IP 地址回来 接下来是 TCP 握手 ...
随机推荐
- Bomb Enemy 炸弹人
Given a 2D grid, each cell is either a wall 'W', an enemy 'E' or empty '0' (the number zero), return ...
- USACO Training Section 1.1黑色星期五Friday the Thirteenth
题目描述 13号又是一个星期五.13号在星期五比在其他日子少吗?为了回答这个问题,写一个程序,要求计算每个月的十三号落在周一到周日的次数.给出N年的一个周期,要求计算1900年1月1日至1900+N- ...
- ACM-ICPC 2019 山东省省赛总结
五题手快拿银,不然拿铜,甚至不拿,从结果上来看拿了铜牌对第一年的我们来说算好的,也不算太好. 从拿奖后的第一天,我想写这篇博客,但是我忍了下来,那时候被喜悦冲昏了头脑,当 冷静下来,我开始打算写这篇博 ...
- P1522 牛的旅行 Cow Tours(floyd)
题目描述 农民 John的农场里有很多牧区.有的路径连接一些特定的牧区.一片所有连通的牧区称为一个牧场.但是就目前而言,你能看到至少有两个牧区通过任何路径都不连通.这样,Farmer John就有多个 ...
- bzoj 4152[AMPPZ2014]The Captain
bzoj 4152[AMPPZ2014]The Captain 给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用. ...
- SSM框架完整开发流程
----------------第一阶段-------------- 1.数据库建模 2.生成sql语句 3.在mysq客户端使用命令方式执行sql脚本,生成数据库 4.允许远程访问mysql GRA ...
- django最全面的知识点,直接开发完整手机购物商城练手,
带手机验证码登陆, 带全套购物车系统 带数据库 前后端分离开发 带定位用户功能 数据库代码为本地制作好了 带支付宝支付系统 带django开发服务器接口教程 地址: https://www.duans ...
- IDEA2020版使用
idea2020版本出来了,不知道小伙伴使用了吗?是不是还在为激活而烦恼呢?我来给小伙伴解决烦恼了,直接上硬货,解决方法我是在B站找到,所以分享出来! 1.直接进IDEA官网下载最近的idea,官网连 ...
- jacoco 生成单测覆盖率报告
一.jacoco 简介 jacoco 是一个开源的覆盖率工具,它针对的开发语言是 java.其使用方法很灵活,可以嵌入到 ant.maven 中:可以作为 Eclipse 插件:可以作为 javaAg ...
- window下用notepad++编辑了脚本文件然后放在linux报错显示无法运行
首先vi :set ff 查看文件类型 接着 下载dos2unix root用户下yum -y install dos2unix 然后 dos2unix 文件.sh 转换格式 接着在正常启动即可