1. 数组封装
1.1 需求
数组操作,相对还是比较复杂的,也不能做添加和删除操作,当需要添加和删除的时候需要新建数组,复制数组,或者
元素移位,比较麻烦
所以 我们对这些添加和删除操作进行封装
1.2 编码实现
package day_01;
public class Array {
/**
* 封装的数组
*/
private Object[] elements;
/**
* 数组中已有元素个数
*/
private int size = 0;
public Array() {
// 数组默认长度为 10
elements = new Object[10];
}
/**
* 获取元素个数
*
* @return
*/
public int size() {
return size;
}
/**
* 根据索引获取数据
*
* @param index
* @return
*/
public Object get(int index) {
// 如果index >= size 说明 不存在
if (index >= size) {
throw new ArrayIndexOutOfBoundsException(index);
}
return elements[index];
}
/**
* 更改
*
* @param index
* @param element
*/
public void set(int index, Object element) {
// 如果index >= size 说明 不存在
if (index >= size) {
throw new ArrayIndexOutOfBoundsException(index);
}
elements[index] = element;
}
/**
* 向数组中添加元素
*
* @param element
*/
public void add(Object element) {
// 1 判断数组中是否满了
if (size == elements.length) {
// 1.2 满了 就扩容,复制数组,再放进去
// 扩容为原来的二倍
Object[] newArr = new Object[size << 1];
// 数组复制
System.arraycopy(elements, 0, newArr, 0, size);
// 赋值
elements = newArr;
}
// 添加进去,size++
elements[size] = element;
size++;
}
/**
* 删除指定元素
*
* @param index
*/
public void remove(int index) {
// 如果index >= size 说明 不存在
if (index >= size) {
throw new ArrayIndexOutOfBoundsException(index);
}
// 移位
for (int i = index; i < size - 1; i++) {
elements[index] = elements[index + 1];
}
// 最后一位赋值为null
elements[size - 1] = null;
// 个数-1
size--;
}
}
1.3 测试
public static void main(String[] args) {
// 创建对象
Array arr = new Array();
// 元素个数
System.out.println(arr.size());
// 尾部添加
arr.add(1);
arr.add(12);
arr.add(13);
arr.add(14);
arr.add(15);
System.out.println(arr.size());
// 更改
arr.set(0, "张三");
for (int i = 0; i < arr.size(); i++) {
// 获取
System.out.println(arr.get(i));
}
System.out.println("====");
// 删除
arr.remove(3);
for (int i = 0; i < arr.size(); i++) {
System.out.println(arr.get(i));
}
}
2. 集合
2.1 概述
Java集合是使程序能够存储和操纵元素不固定的一组数据。 所有Java集合类都位于java.util包中。
【问】:之前我们需要把多个元素放到一起的时候,使用的是数组。那么为何还要提供Java集合工具类呢?
我们通过对比数组和Java集合工具类来解释Java集合工具类的必要性。
数组 | 集合 |
---|---|
长度固定 | 长度不固定 |
存放任意类型 | 不能存放基本数据类型,只能存放对象的引用 |
注意:如果集合中存放基本类型,一定要将其 “装箱”成对应的”基本类型包装类”。
2.2 继承体系
Collection 是集合,两个直接子接口是List和set
List 特性 : 有序 可重复,保证数据的添加顺序和取出顺序一致
Set 特性 : 无序 不可重复,不能保证数据的添加和取出顺序一致
List 有三个子类 :
ArrayList : 底层是数组,查询和更改效率极高
LinkedList : 底层是双向链表,添加和删除效率要高一些
Vector : 底层也是数组,是线程安全,已废弃,不推荐使用,已被ArrayList代替
Set有两个子类
HashSet : 底层是散列表
TreeSet : 底层是二叉树
2.3 Collection
Collection作为集合类的父类,所以,collection中的方法,是所有集合类都有的方法
2.3.1 常用方法
2.3.2 使用方式
以ArrayList为例
public static void main(String[] args) {
// 创建一个ArrayList对象
Collection collection = new ArrayList();
// 判断是否为空
System.out.println(collection.isEmpty());
// 已有元素个数
System.out.println(collection.size());
// 添加 , 如果添加一个基本类型,则会进行自动装箱为对应的包装类类型,然后再发生多态转型为Object类型
collection.add(1);
collection.add(3);
collection.add(2);
collection.add("张三");
System.out.println(collection.size());
System.out.println(collection);
// 删除指定元素,注意 不是索引,是根据数据删除
collection.remove("张三");
System.out.println(collection);
// 转换为数组
Object[] arr = collection.toArray();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
// 清空集合中的数据
collection.clear();
System.out.println(collection.size());
}
2.3.3 Iterator
迭代器
* Iterator 迭代器
* 迭代器是一种模式,它可以使遍历和被遍历的对象相分离,我们就不再关心底层是什么数据结构,是如何进行数据存储的
* 只要拿到迭代器对象,就可以进行遍历
*
* collection中 提供了一个 iterator() 方法 用于获取迭代器对象
* 集合.iterator();
*
* 迭代器中,有三个方法
* 1 boolean hasNext() : 判断游标下是否还有元素,默认指向顶端,并没有指向第一个元素
* 2 E next() : 将迭代器游标向下移动一位,并取出该元素
* 3 remove () : 删除当前执行的元素,会把集合中的也删除
*
* 迭代器一旦创建,集合不能添加和删除,如果添加和删除了,需要重新生成迭代器
*
* 增强for循环forEach 就是迭代器的简写方式
public static void main(String[] args) {
// 创建
Collection c = new ArrayList();
// 添加
c.add(1);
c.add(11);
c.add(12);
c.add(13);
c.add(14);
// 生成迭代器
Iterator it = c.iterator();
// 生成迭代器之后,不能添加和删除,除非重新生成!!!
// c.add(14);
while (it.hasNext()) {
Object o = it.next();
System.out.println(o);
}
// 迭代器使用完之后,想要再次使用,需要重新生成,因为光标已经指向最后一个了
it = c.iterator();
while (it.hasNext()) {
Object o = it.next();
System.out.println(o);
}
}
2.3.4 注意
* contains(Object o) : 判断是否包含某个元素
*
* remove(Object o ) : 删除指定元素
*
* 这两个方法,底层都会去调用equals方法进行比较
public class Collection_03 {
public static void main(String[] args) {
Collection c = new ArrayList();
Integer i1 = new Integer(1235);
Integer i2 = new Integer(1235);
c.add(i1);
// true
System.out.println(c.contains(i1));
// true 因为 Integer 覆写了equals方法 比较的值
System.out.println(c.contains(i2));
// 当我们保存的自定义类对象的时候,需要使用contains和remove的时候要注意覆写equals方法
c = new ArrayList();
Manager m1 = new Manager(1, "ABC");
Manager m2 = new Manager(1, "ABC");
c.add(m1);
System.out.println(c.contains(m1));
System.out.println(c.contains(m2));
System.out.println(c);
}
}
class Manager{
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Manager) {
Manager m1 = (Manager) obj;
if (m1.no == this.no && this.name.equals(m1.name)) {
return true;
}
}
return false;
}
int no;
String name;
public Manager(int no, String name) {
super();
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "Manager [no=" + no + ", name=" + name + "]";
}
}
2.4 forEach
public static void main(String[] args) {
int[] arr = {1,2,3};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
// ------
// 会把 数组中每个元素 赋值给 变量 element 不是下标
for (int element : arr) {
System.out.println(element);
}
Collection c = new ArrayList();
c.add("a");
c.add("b");
c.add("c");
// foreach是迭代器的简写方式,所以功能有限,只能查询,不能删除
// 想要在遍历中删除,需要使用迭代器的remove
for (Object object : c) {
System.out.println(object);
}
}
2.5 List
2.5.1 ArrayList
* List 特性 : 有序 可重复,保证数据的添加顺序和取出顺序一致
List 有三个子类 :
ArrayList : 底层是数组,查询和更改效率极高 ,默认初始化容量为10,扩大为原来的1.5倍,非线程安全
创建对象的时候,没有容量,就是0 , 当第一次添加数据的时候,才会初始化容量
1.5倍 oldCapacity + (oldCapacity >> 1);
LinkedList : 底层是双向链表,添加和删除效率要高一些
Vector : 底层也是数组,是线程安全,已废弃,不推荐使用,已被ArrayList代替,默认认初始化容量为10,扩大为原来的2倍
List list = new ArrayList();
// 集合中只能保存引用数据类型,如果添加的是基本类型的话,
// 会先进行自动装箱为对应的包装类,然后发生多态转型为Object类型
// add(E e) : 尾部添加
list.add(1);
list.add(2);
// add(int index,E e) : 把元素插入到指定位置,非特殊情况,尽量不用,因为其他元素需要向后移位
list.add(0,3);
// set(int index,E e) : 更改指定索引的元素值
list.set(1, 4);
// get(int index) : 获取对应索引的元素值
System.out.println(list.get(0));
// list中 remove方法有重载
// 如果传入的是 int值 则是删除对应索引的元素 , 根据索引删除
// 如果传入引用类型的值,则是删除对应的数据 , 根据元素值删除
// 删除索引为0的元素
list.remove(0);
// 删除 值为4的元素
list.remove(new Integer(4));
System.out.println(list);
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(4);
list.add(11);
list.add(10);
// 对list进行升序排序
Collections.sort(list);
System.out.println(list);