这是我参与 8 月更文挑战的第 28 天,活动详情查看:8 月更文挑战
ArrayList
与数组的区别
- 数组局限性 : 当要存放多个对象时,如果对象数量不确定,就难以新建数组,因为数组长度一旦固定就不再可变;为解决这一局限性,引入容器
ArrayList,其容量会随对象增加而不断自动改变,不用担心边界问题;
import java.util.ArrayList;
public class Demo{
public static void main(String[] args){
int[] array = new int[10];
arr[0] = 10;
arr[20] = 3; // 越界
// 不用担心边界问题
ArrayList<Integer> list = new ArrayList<>();
list.add(24);
list.add(54);
}
}
常用方法
| 方法 | 功能 |
|---|---|
add(Object obj)/add(int index, Object obj) | 末尾增加对象/指定索引位置加入对象 |
contains(Object obj) | 判断某对象是否存在容器中 |
get(int index) | 获取指定位置的对象 |
indexOf(Object obj) | 获取对象所处位置 |
remove(Object obj)/remove(int index) | 删除指定对象/指定位置的对象 |
set(int index, Object obj) | 替换指定位置元素 |
size() | 获取容器大小 |
toArray() | 转换为数组 |
addAll(ArrayList arrayList) | 将另一个容器中所有对象加入进来 |
clear() | 清空 |
泛型 Generic
不指定泛型的容器,可以存放任意类型的元素,取出数据时需要转型;指定了泛型的容器,只能存放指定类型的元素及其子类;
遍历
for
import java.util.ArrayList;
import java.util.Iterator;
import java.utils.List;
public class Demo{
public static void main(String[] args){
List<Integer> list = new ArrayList<>();
for(int i = 0; i < 5; i++){
list.add(i + 1);
}
for(int j = 0; j < list.size(); j++){
System.out.println(list.get(j));
}
}
}
for:
import java.util.ArrayList;
import java.util.Iterator;
import java.utils.List;
public class Demo{
public static void main(String[] args){
List<Integer> list = new ArrayList<>();
for(int i = 0; i < 5; i++){
list.add(i + 1);
}
for(Integer num : list){
System.out.println(num);
}
}
}
iterator
import java.util.ArrayList;
import java.util.Iterator;
import java.utils.List;
public class Demo{
public static void main(String[] args){
List<Integer> list = new ArrayList<>();
for(int i = 0; i < 5; i++){
list.add(i + 1);
}
// while 循环
Iterator<Integer> it = list.iterator();
while(it.hasNext()){
Integer num = it.next();
System.out.println(num);
}
// for 循环
for(Iterator<Integer> iterator = list.iterator();iterator.hasNexxt();){
Integer numInt = (Integer) iterator.next();
System.out.println(numInt);
}
}
}
LinkedList
- 序列分为 先进先出 FIFO 和 先进后出 FILO,FIFO 又叫 队列 Queue,FILO 又叫 栈 Stack;
- 双向链表 Deque :方便在头尾增删数据;
import java.util.LinkedList;
public class Demo{
public static void main(String[] args){
LinkedList<Integer> linkedList = new LinkedList<Integer>();
// 在头尾增加数据
linkedList.addFirst(9);
linkedList.addFirst(34);
linkedList.addLast(3);
// 在头尾删除数据
System.out.println(linkedList.removeFirst());
System.out.println(linkedList.removeLast());
// 查看头尾数据
System.out.println(linkedList.getFirst());
System.out.println(linkedList.getLast());
}
}
- 队列 Queue
队列是 FIFO,有如下常用方法;
| 方法 | 功能 |
|---|---|
offer(Object obj) | 在队尾添加元素 |
poll() | 取出队首元素 |
peek() | 查看队首元素 |
import java.util.LinkedList;
import java.util.Queue;
public class Demo{
public static void main(String[] args){
Queue<Integer> queue = new LinkedList<Integer>();
// 队尾添加元素
queue.offer(34);
queue.offer(43);
// 查看队首元素
System.out.println(queue.peek());
// 取出队首元素
System.out.println(queue.poll());
}
}
二叉树
- 定义 :由各种 节点 组成,每个节点可以有 左右子节点,每个节点均有一个 值;
publc class Node{
// 左右节点 + 值
public Node leftNode;
public Node rightNode;
public Object value;
}
- 排序
public class Node {
// 左子节点
public Node leftNode;
// 右子节点
public Node rightNode;
// 值
public Object value;
// 插入 数据
public void add(Object v) {
// 如果当前节点没有值,就把数据放在当前节点上
if (null == value)
value = v;
// 如果当前节点有值,就进行判断,新增的值与当前值的大小关系
else {
// 新增的值,比当前值小或者相同
if ((Integer) v -((Integer)value) <= 0) {
if (null == leftNode)
leftNode = new Node();
leftNode.add(v);
}
// 新增的值,比当前值大
else {
if (null == rightNode)
rightNode = new Node();
rightNode.add(v);
}
}
}
public static void main(String[] args) {
int randoms[] = new int[] { 67, 7, 30, 73, 10, 0, 78, 81, 10, 74 };
Node roots = new Node();
for (int number : randoms) {
roots.add(number);
}
}
}
- 遍历
遍历分为 左序、中序、右序;
- 左序:中间的数遍历后放在左边;
- 中序:中间的数遍历后放在中间;
- 右序:中间的数遍历后放在右边;
/**
* Created with IntelliJ IDEA.
* Version : 1.0
* Author : cunyu
* Email : cunyu1024@foxmail.com
* Website : https://cunyu1943.github.io
* 公众号 : 村雨遥
* Date : 2020/5/15 下午12:40
* Project : mavenDemo
* Package : PACKAGE_NAME
* Class : Node
* Desc : 中序遍历
*/
import java.util.ArrayList;
import java.util.List;
public class Node {
// 左子节点
public Node leftNode;
// 右子节点
public Node rightNode;
// 值
public Object value;
/**
* 插入数据
*
* @param v 待插入的数据
*/
public void add(Object v) {
// 如果当前节点没有值,就把数据放在当前节点上
if (null == value)
value = v;
// 如果当前节点有值,就进行判断,新增的值与当前值的大小关系
else {
// 新增的值,比当前值小或者相同
if ((Integer) v - ((Integer) value) <= 0) {
if (null == leftNode)
leftNode = new Node();
leftNode.add(v);
}
// 新增的值,比当前值大
else {
if (null == rightNode)
rightNode = new Node();
rightNode.add(v);
}
}
}
/**
* 中序遍历
* @return 中序遍历后的 List
*/
public List<Object> middleIterator() {
List<Object> values = new ArrayList<>();
// 左节点的遍历结果
if (null != leftNode)
values.addAll(leftNode.middleIterator());
// 当前节点
values.add(value);
// 右节点的遍历结果
if (null != rightNode)
values.addAll(rightNode.middleIterator());
return values;
}
/**
* 左序遍历
*
* @return 左序遍历后的 List
*/
public List<Object> forwardIterator() {
List<Object> values = new ArrayList<>();
values.add(value);
if (null != leftNode) {
values.add(leftNode.forwardIterator());
}
if (null != rightNode) {
values.add(rightNode.forwardIterator());
}
return values;
}
/**
* 右序遍历
* @return 右序遍历后的数组
*/
public List<Object> behindIterator() {
List<Object> values = new ArrayList<>();
if (null != leftNode) {
values.add(leftNode.forwardIterator());
}
if (null != rightNode) {
values.add(rightNode.forwardIterator());
}
values.add(value);
return values;
}
public static void main(String[] args) {
int[] randoms = new int[]{67, 7, 73};
Node roots = new Node();
for (int number : randoms) {
roots.add(number);
}
System.out.println(roots.middleIterator());
System.out.println(roots.forwardIterator());
System.out.println(roots.behindIterator());
}
}
HashMap
HashMap 是通过 键值对 的方式存储数据,其中 键是唯一的,值是可以重复的,所以当以同样的 key 将不同 value 加到 HashMap 将导致原来的元素被覆盖;
/**
* Created with IntelliJ IDEA.
* Version : 1.0
* Author : cunyu
* Email : cunyu1024@foxmail.com
* Website : https://cunyu1943.github.io
* 公众号 : 村雨遥
* Date : 2020/5/15 下午1:05
* Project : mavenDemo
* Package : PACKAGE_NAME
* Class : Demo
* Desc :
*/
import java.util.HashMap;
public class Demo {
public static void main(String[] args) {
HashMap<String, String> dict = new HashMap<>();
dict.put("坦克", "牛头");
dict.put("射手", "伽罗");
dict.put("射手", "后裔");
System.out.println(dict.get("射手"));
}
}
HashSet
HashSet中 元素不能重复,而且是无序的;
/**
* Created with IntelliJ IDEA.
* Version : 1.0
* Author : cunyu
* Email : cunyu1024@foxmail.com
* Website : https://cunyu1943.github.io
* 公众号 : 村雨遥
* Date : 2020/5/15 下午1:05
* Project : mavenDemo
* Package : PACKAGE_NAME
* Class : Demo
* Desc :
*/
import java.util.HashSet;
public class Demo {
public static void main(String[] args) {
HashSet<String> names = new HashSet<>();
names.add("后羿");
names.add("伽罗");
System.out.println(names);
// 插入相同数据,容器中只保留一个
names.add("后羿");
System.out.println(names);
}
}
- 遍历 :
HashSet无序,所以无法通过get()获取指定位置元素,只能通过 迭代器或增强型for循环 来遍历;
/**
* Created with IntelliJ IDEA.
* Version : 1.0
* Author : cunyu
* Email : cunyu1024@foxmail.com
* Website : https://cunyu1943.github.io
* 公众号 : 村雨遥
* Date : 2020/5/15 下午1:05
* Project : mavenDemo
* Package : PACKAGE_NAME
* Class : Demo
* Desc :
*/
import java.util.HashSet;
import java.util.Iterator;
public class Demo {
public static void main(String[] args) {
HashSet<String> names = new HashSet<>();
names.add("后羿");
names.add("伽罗");
System.out.println(names);
// 增强 for 循环遍历
for (String name : names) {
System.out.println(name);
}
// 迭代器遍历
for (Iterator<String> iterator = names.iterator();iterator.hasNext();){
String name = (String) iterator.next();
System.out.println(name);
}
}
}
HashMap 和 HashSet 的区别
HashSet 没有独立的实现,而是在其中封装了一个 Map,HashSet 是作为 Map 的 key 而存在的,而 value 是一个名为 PRESENT 的静态对象,属于类属性,有且只有一个;
private static final Object PRESENT = new Object();
/**
* HashSet 源码
*/
import java.util.AbstractSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
//HashSet里封装了一个HashMap
private HashMap<E,Object> map;
private static final Object PRESENT = new Object();
//HashSet的构造方法初始化这个HashMap
public HashSet() {
map = new HashMap<E,Object>();
}
//向HashSet中增加元素,其实就是把该元素作为key,增加到Map中
//value是PRESENT,静态,final的对象,所有的HashSet都使用这么同一个对象
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
//HashSet的size就是map的size
public int size() {
return map.size();
}
//清空Set就是清空Map
public void clear() {
map.clear();
}
//迭代Set,就是把Map的键拿出来迭代
public Iterator<E> iterator() {
return map.keySet().iterator();
}
}
Collection vs Collections
Collection
Collection 是 Set、List、Queue、Deque 的接口;
graph TB
A[Collection] --- B[Set]
A[Collection] --- C[List]
A[Collection] --- D[Queue]
A[Collection] --- E[Deque]
B[Set] --- F[SortedSet]
C[List] --- G[ArrayList]
C[List] --- H[LinkedList]
C[List] --- I[Vector]
Collections
Collections 是一个类,容器的工具类,如同 Arrays 数组的工具类。主要有如下常用方法:
| 方法 | 功能 |
|---|---|
reverse(List<?> list) | 反转 |
shuffle(List<?> list) | 打乱 |
sort(List<?> list) | 从小到大排序 |
swap(List<?> list, int i, int j) | 交换 i,j 两个位置的元素 |
rotate(List<?> list, int distance) | 向右滚动 distance 个单位 |
synchronizedList(List<?> list) | 将非线程安全的 List 转换为线程安全的 List |
/**
* Created with IntelliJ IDEA.
* Version : 1.0
* Author : cunyu
* Email : cunyu1024@foxmail.com
* Website : https://cunyu1943.github.io
* 公众号 : 村雨遥
* Date : 2020/5/15 下午1:05
* Project : mavenDemo
* Package : PACKAGE_NAME
* Class : Demo
* Desc :
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class Demo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(i + 1);
}
System.out.println(list);
// 翻转
Collections.reverse(list);
System.out.println(list);
// 打乱
Collections.shuffle(list);
System.out.println(list);
// 排序
Collections.sort(list);
System.out.println(list);
// 交换
Collections.swap(list, 3, 4);
System.out.println(list);
// 向右滚动
Collections.rotate(list, 3);
System.out.println(list);
List<Integer> synchronizedNumList = (List<Integer>) Collections.synchronizedList(list);
System.out.println(synchronizedNumList);
}
}
关系与区别
ArrayList vs HashSet
-
ArrayList:有顺序,数据能够重复; -
HashSet:无顺序(既不是插入顺序,也不是hashcode的顺序),数据不能重复; -
判断是否重复的标准 :
- 若
hashcode不同 :则认为是不同数据; - 若
hashcode相同 : 比较equals,若equals相同,则是相同数据,否则不是;
- 若
ArrayList vs LinkedList
ArrayList:插入、删除数据较慢,属于顺序结构,因此定位快;LinkedList:插入、删除数据较快,属于链表结构,因此定位慢;
HashMap vs HashTable
两者都是实现了 Map 接口,都以 键值对 的方法保存数据;
HashMap:能够存放null,不是线程安全的类;HashTable:不能存放null,是线程安全的类
几种 Set
HashSet:无序LinkedHashSet:按照插入顺序;TreeSet:从小到大排序;
其他
比较器
Comparator
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
class Hero{
public String name;
public float hp;
public int damage;
public Hero() {
}
public Hero(String name) {
this.name = name;
}
public String toString() {
return "Hero [name=" + name + ", hp=" + hp + ", damage=" + damage + "]\r\n";
}
public Hero(String name, int hp, int damage) {
this.name = name;
this.hp = hp;
this.damage = damage;
}
}
public class TestCollection {
public static void main(String[] args) {
Random r =new Random();
List<Hero> heros = new ArrayList<Hero>();
for (int i = 0; i < 10; i++) {
//通过随机值实例化hero的hp和damage
heros.add(new Hero("hero "+ i, r.nextInt(100), r.nextInt(100)));
}
System.out.println("初始化后的集合:");
System.out.println(heros);
//直接调用sort会出现编译错误,因为Hero有各种属性
//到底按照哪种属性进行比较,Collections也不知道,不确定,所以没法排
//Collections.sort(heros);
//引入Comparator,指定比较的算法
Comparator<Hero> c = new Comparator<Hero>() {
@Override
public int compare(Hero h1, Hero h2) {
//按照hp进行排序
if(h1.hp>=h2.hp)
return 1; //正数表示h1比h2要大
else
return -1;
}
};
Collections.sort(heros,c);
System.out.println("按照血量排序后的集合:");
System.out.println(heros);
}
}
Comparable
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
class Hero implements Comparable<Hero>{
public String name;
public float hp;
public int damage;
public Hero(){
}
public Hero(String name) {
this.name =name;
}
//初始化name,hp,damage的构造方法
public Hero(String name,float hp, int damage) {
this.name =name;
this.hp = hp;
this.damage = damage;
}
@Override
public int compareTo(Hero anotherHero) {
if(damage<anotherHero.damage)
return 1;
else
return -1;
}
@Override
public String toString() {
return "Hero [name=" + name + ", hp=" + hp + ", damage=" + damage + "]\r\n";
}
}
public class Demo {
public static void main(String[] args) {
Random r =new Random();
List<Hero> heros = new ArrayList<Hero>();
for (int i = 0; i < 10; i++) {
//通过随机值实例化hero的hp和damage
heros.add(new Hero("hero "+ i, r.nextInt(100), r.nextInt(100)));
}
System.out.println("初始化后的集合");
System.out.println(heros);
//Hero类实现了接口Comparable,即自带比较信息。
//Collections直接进行排序,无需额外的Comparator
Collections.sort(heros);
System.out.println("按照伤害高低排序后的集合");
System.out.println(heros);
}
}
总结
以上就是今天关于 Java 集合的相关知识总结了,如果你觉得我的文章对你有所帮助,那就点赞关注我吧!