集合(1)

# 集合

集合是一个可以存放引用数据类型的容器,大小不固定。
集合的顶级接口是Collection

“`“` :泛型,就是集合中存放的数据类型。只能是引用数据类型,不能是基本数据类型

## 集合特点

提供一种存储空间可变的存储模型,存储数据的容量可以发生改变

在数组装满的情况下 自动扩容
1.数组
2.链表
3.树
4.队列

## 集合常用方法

“`java
import java.util.ArrayList;
import java.util.Collection;

public static void main(String[] args) {
//ArrayList<>()方法
Collection collection = new ArrayList<>();
//添加元素
collection.add(“123”);
collection.add(“456”);

//清空集合
collection.clear();

//判断是否包含某一元素
//contains()
System.out.println(collection.contains(“123”));
System.out.println(collection);

//判断集合是否为空
//isEmpty()
System.out.println(collection.isEmpty());

//获取集合中的元素个数
System.out.println(collection.size());

//把集合转换成数组
Object[] objects = collection.toArray(new String[0]);
for (String object : objects) {
System.out.println(object);
}
System.out.println(collection);
}

“`

## List 接口

特点:

1. 有序
2. 可以存放重复的元素
3. 方法中有索引

“`java
import java.util.ArrayList;

public static void main(String[] args) {
//List接口
List list = new ArrayList<>();
//添加数据
list.add(“java”);
//插入元素
list.add(2, “JAVA”);
//根据索引获取元素
String s = list.get(3);
System.out.println(s);

//获取元素首次出现的索引
int index = list.indexOf(“java”);
System.out.println(index);

//获取元素最后一次出现的索引
int JAVA = list.lastIndexOf(“JAVA”);
System.out.println(JAVA);

//根据索引删除元素
String remove = list.remove(2);
System.out.println(remove);

//修改给出索引处的元素
list.set(2, “C++”);

//截取子列表 包头不包尾
List strings = list.sublist(1, 2);
System.out.println(strings);
System.out.println(list);
}
“`

## ArrayList

JDK封装好的ArrayList/Map/Set

原生数组存放数据 在开始定义时容量固定 因此会无法存放

### 特点:

底层的数据结构是数组,因此内存是连续的

ArrayList的查询速度相对更快

ArrayList的增加和删除速度相对慢

ArrayList是线程不安全的集合

调用无参构造,会创建一个长度为0的Object类型的数组

当第一次调用add方法时,会创建一个长度为10的数组。

ArrayList默认内容是10

扩容 = 原本容量 + 原本容量 / 2

当调用有参构造指定初始化容量时,指定多少就是多少

## 实例

“`java
import java.util.ArrayList;

public class TestDemo {
public static void main(String[] args) {
/**
* new ArrayList<泛型>
*/
list arrayList = new ArrayList();//集合容器中只能存入 String 类型
//arrayList 对象名称
arrayList.add(“mayikt”);
}
}
“`

## 方法实例

“`java
import java.util.ArrayList;

public static void main(String[] args) {
// list接口

List list = new ArrayList<>(16);
//添加数据
list.add(“java”);
list.add(“C”);
list.add(“C#”);
list.add(“.net”);
list.add(“golang”);
list.add(“python”);
list.add(“python”);

//插入元素
list.add(2, “PHP”);

//根据索引获取元素
String s = list.get(3);
System.out.println(s);

//获取元素首次出现的索引
int index = list.indexOf(“丁真”);
System.out.println(index);

// 获取元素最后一次出现的索引
int python = list.lastIndexOf(“python”);
System.out.println(python);
// 根据索引删除元素
String remove = list.remove(2);
System.out.println(remove);

// 修改指定索引处的元素
list.set(1, “怪0”);

// 截取子列表 包头不包尾
List strings = list.subList(1, 5);
System.out.println(strings);
System.out.println(list);
}
“`

## 功能实现

## 实现ArrayList

“`java
import java.util.Arrays;

public class ArrayListDemo {
private String[] data;
private int size = 0;

public ArrayListDemo() {
data = new String[0];
}

private void grow() {
if (data.length == 1) {
data = Arrays.copyOf(data, data.length + 1);
} else data = Arrays.copyOf(data, data.length + (data.length >> 1));
}

private void isIndexOutOfBound(int index) {
if (index < 0 || index >= data.length) throw new IndexOutOfBoundsException();
}

/*
* 添加元素
* */

public void add(String str) {
if (data.length == 0) data = new String[10];
//判断是否需要扩容
if (size >= data.length) {
grow();
}
data[size] = str;
size++;
}

/*
* 插入元素
* */

public void insert(int index, String str) {
//判断索引是否越界
isIndexOutOfBound(index);
//判断是否需要扩容
//两种情况,插入在数组内,插入在数组最后一个
if (size >= data.length) {
grow();
}
//方法一 循环
// for(int i = 0; i < size; i++) {
// data[i+1] = data[i];
// }
//方法二 arraycopy()
System.arraycopy(data, index, data, index + 1, size – index);

data[index] = str;
size++;

}
//删除指定元素

public void remove(int index) {
//判断索引是否越界
isIndexOutOfBound(index);
//方式一 循环
// for (int i = 0; i < index; i++) {
// data[i] = data[i + 1];
// }
//方法二 arraycopy()
System.arraycopy(data, index + 1, data, index, size – index – 1);
size–;
}

@Override
public String toString() {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("[");
for (int i = 0; i < size; i++) {
if (i != size – 1) stringBuffer.append(data[i]).append(",");
else {
stringBuffer.append(data[i]);
}
}
stringBuffer.append("]");
return stringBuffer.toString();
}
}
“`

## LinkedList

– LinkedList底层数据结构是双向不循环链表
– LinkedList的内存是不连续的
– LinkedList查询相对慢
– LinkedList增删相对快
– LinkedList线程不安全

## 实现LinkedList

“`java
import java.util.Objects;

public class LinkedListDemo {
private int size;
private Node first;
private Node last;

private class Node {
String item;
Node next;
Node prev;

public Node(String item, Node next, Node prev) {
this.item = item;
this.next = next;
this.prev = prev;
}

}

private void isIndexOutOfBound(int index) {
if (index > size || index < 0) throw new IndexOutOfBoundsException();
}

private Node getNode(int index) {
Node targetNode = first;
for (int i = 0; i < index; i++) {
targetNode = targetNode.next;
}
return targetNode;
}

/*
* 添加元素方法
* */

public void addNode(String str) {
//添加元素分两种情况
//1. 第一次添加,头结点和尾结点相同
//2. 第n次添加,需要把新添加的结点设为尾结点

//创建结点

Node node = new Node(str, null, null);
if (size == 0) {
first = node;
} else {
last.next = node;
}
last = node;
size++;
}

/*
* 插入元素
* @param index 插入的索引
* @param str 插入的内容
* */

public void insert(int index, String str) {
//判断索引是否越界
isIndexOutOfBound(index);
//双向链表插入分三种情况,头部,中间,尾部

//插入尾部
if (index == size) {
addNode(str);
}
Node newnode = new Node(str, null, null);
if (size == 0) {
//插入头部
newnode.next = first;
first.prev = newnode;
first = newnode;
} else {
//插入中间,需要先寻找索引处的结点
//通过封装好的方法,遍历链表找到对应需要插入的结点位置
Node nextnode = getNode(index);
//找到的后结点指向的前结点的后结点为新结点
nextnode.prev.next = newnode;
//新结点指向的前结点为前结点
newnode.prev = nextnode.prev;
//新节点指向的后结点为后结点
newnode.next = nextnode;
//后结点指向的前结点为新结点
nextnode.prev = newnode;
}
size++;
}

//删除元素
public void remove(int index) {
isIndexOutOfBound(index);
//删除元素分三种情况,删除头节点 尾结点 中间结点

//删除头部结点
if (index == 0) {
first = first.next;
first.prev = null;
}
//删除尾部结点
else if (index == size – 1) {
last = last.prev;
last.next = null;
}
//删除中间结点
else {
Node targetNode = getNode(index);
targetNode.prev.next = targetNode.next;
targetNode.next.prev = targetNode.prev;
}
size–;
}

/*
* 查询指定元素首次出现的索引
* 按字符串查找
* */
public int indexOf(String str) {
Node node = first;
for (int i = 0; i < size; i++) {
if (Objects.equals(node.item, str))
return i;
node = node.next;
}
return -1;//如果未找到返回-1
}

/*
*删除指定元素
* 调用查找指定元素的方法
* 调用删除元素的方法
* */

public void remove(String str) {
int i = indexOf(str);
if (i != -1) {
remove(i);
}
}

/*
* 判断链表中是否包含某元素
* */

public boolean contains(String str) {
return indexOf(str) != -1;
}
}

“`

## LinkedList的增删改查操作图解

### 个人理解

### **主要思想是利用找到的新结点的后结点的指针定位新结点的前结点**

![第0步.png](http://43.155.216.63:21080/wp-content/uploads/2025/12/%E7%AC%AC0%E6%AD%A5.png

### **先更改前结点指向的后结点和新结点指向的前结点(第一步和第二步)**

![第1步.png](http://43.155.216.63:21080/wp-content/uploads/2025/12/%E7%AC%AC1%E6%AD%A5.png

![第2步.png](http://43.155.216.63:21080/wp-content/uploads/2025/12/%E7%AC%AC2%E6%AD%A5.png

### **再更改后结点指向的前结点和新结点指向的后结点(第三步和第四步)**

![第3步.png](http://43.155.216.63:21080/wp-content/uploads/2025/12/%E7%AC%AC3%E6%AD%A5.png

![第4步.png](http://43.155.216.63:21080/wp-content/uploads/2025/12/%E7%AC%AC4%E6%AD%A5.png

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇