Java 中集合
1 - 集合的概述
编程的时候如果需要存储多个数据,使用长度固定的数组格式,不一定能满足我们的需求,为了适应不同长度的数据存储需求,Java 给我们提供了集合,来解决这个问题
集合的特点:存储空间是可变的
- 单列集合 Collection
- List 可以重复的:ArrayList、LinkedList …
- Set 不可重复的:HashSet、TreeSet …
- 双列集合 Map:HashMap、TreeMap …
注:加粗 为 接口、 斜体 为 实现类
2 - ArrayList
ArrayList<E>
- 可以调整大小的数组的实现
<E>
:一种特殊的数据类型,泛型
2.1 - ArrayList 构造方法和添加成员方法
方法名 | 说明 |
---|---|
public ArrayList<E>() | 创建一个新的空集合 |
public boolean add(E e) | 将指定的元素添加到集合当中 |
public void add(int index, E e) | 将指定的元素添加到集合的指定位置当中 |
package advanced.demo;
import java.util.ArrayList;
/**
* @author Object
* @description ArrayList构造方法和添加成员方法
* @date 2020/9/6
*/
public class Demo01 {
public static void main(String[] args) {
//通过构造方法创建ArrayList对象,创建了一个字符串集合
ArrayList<String> list = new ArrayList<>();
//通过add(E e)方法往集合中添加元素
list.add("Hello");
list.add("World");
//输出一下集合,查看信息是否添加成功
System.out.println(list);
//通过 add(int index )往指定索引位置新增元素
list.add(1,"We");
//输出一下集合,查看信息是否添加成功
System.out.println("================");
System.out.println(list);
}
}
//运行结果
[Hello, World]
================
[Hello, We, World]
2.2 - ArrayList 集合中的常用方法
方法名 | 说明 |
---|---|
public boolean remove(Object o) | 删除指定的元素,返回是否成功 |
public E remove(int index) | 删除指定索引对应的元素,返回被删除的元素 |
public E set(int index , E e) | 修改指定位置的元素,返回修改的元素(原) |
public E get(int index) | 获取指定索引位置的元素 |
public int size() | 返回集合中元素的个数 |
package advanced.demo;
import java.util.ArrayList;
/**
* @author Object
* @description ArrayList集合中的常用方法
* @date 2020/9/6
*/
public class Demo02 {
public static void main(String[] args) {
//通过构造方法创建ArrayList对象,创建了一个字符串集合
ArrayList<String> list = new ArrayList<>();
//通过add(E e)方法往集合中添加元素
list.add("Hello");
list.add("World");
list.add("Test");
list.add("java");
list.add("c++");
list.add("python");
System.out.println("添加元素之后集合-->"+list);
//通过remove(Object o)方法,移除集合中的元素,返回值为布尔类型
System.out.println(list.remove("Hello"));
System.out.println("删除元素之后集合-->"+list);
//通过remove(int index)方法删除指定位置的元素,返回被删除的元素
System.out.println("删除索引位置的元素"+list.remove(1));
//通过 get(int index)获取集合索引位置的元素,返回获取的元素
System.out.println("获取指定索引位置的元素"+list.get(0));
System.out.println("修改前的列表元素-->"+list);
//通过 set(int index,E e),修改指定索引位置的元素,返回修改之前的元素
System.out.println("被修改的元素"+list.set(0,"AAAA"));
System.out.println("修改后的列表元素-->"+list);
//通过size()方法获取集合元素的个数,返回值int
System.out.println(list.size());
}
}
//运行结果
添加元素之后集合-->[Hello, World, Test, java, c++, python]
true
删除元素之后集合-->[World, Test, java, c++, python]
删除索引位置的元素Test
获取指定索引位置的元素World
修改前的列表元素-->[World, java, c++, python]
被修改的元素World
修改后的列表元素-->[AAAA, java, c++, python]
4
Process finished with exit code 0
3-Collection
3.1-概述
Collection是单列集合的顶级接口,它由子类实现,它可以表示一组对象,其中每个对象都是这个集合的一个元素。
3.2-Collection 常用方法
方法名 | 说明 |
---|---|
boolean add(E e) | 添加元素 |
boolean remove(Object o) | 删除元素,返回布尔值 |
void clear() | 清空集合 |
boolean isEmpty() | 判断集合是否为空 |
boolean contains(Object o) | 判断元素是否在集合中 |
int size() | 获取集合元素个数 |
3.3-迭代器
-
Iterator
:迭代器,集合的专属遍历方式 -
迭代器获取对象:
Iterator<E> interator
:通过集合中的iterator ()方法返回集合的迭代对象。 -
迭代器中的常用方法
方法名 说明 next() 返回下一个元素 boolean hasNext() 判断集合中下一个元素存不存在 import java.util.*; public class Demo{ public static void main(String[] args){ //创建一个集合 Collection<String> collection = new ArrayList<>(); //添加元素 collection.add("zhangsan"); collection.add("lisi"); collection.add("wangwu"); //通过iterator()方法获得集合迭代器对象 Iterator<String> it = collection.iterator(); //判断集合下一个元素是否存在 while(it.hasNext()){ //输出集合下一个元素 System.out.println(it.next()); } } }
4-List
4.1-概述
- 有序集合,可根据指定的索引对集合进行访问或者插入等操作。
- list集合允许重复数据的元素,Set集合不允许出现重复元素(添加不进去)。
4.2-List集合中的常用方法
方法名 | 说明 |
---|---|
void add(int index ,E e) | 在集合指定的位置插入元素 |
E remove(int index) | 删除集合指定位置的元素 |
E set(int index ,E e) | 修改指定位置的元素 |
E get(int index) | 获取指定位置的元素 |
import java.util.*;
public class Demo{
public static void main(String[] args){
//创建一个集合
List<String> list = new ArrayList<>();
//添加元素
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
//删除元素
System.out.println("删除的元素是-->"+list.remove(0));
//修改元素
System.out.println("修改的元素是-->"+list.set(0,"huangsan"));
//查询元素
System.out.println("查询的元素是-->"+list.get(0));
//获取集合元素个数
System.out.println("集合元素个数是-->"+list.size());
}
}
4.3-插入算法(数组)
import java.util.*;
public class Demo{
public static void main(String[] args){
//创建一个数组,长度为10
int[] arr = new int[10];
//给数组赋值,为了模拟插入功能,这里只赋9个值,最后一个不赋值
for(int i=0;i <arr.length-1;i++){
arr[i]=i+1;
}
//调用方法往数组指定的位置插入一个数
int index=3;
int value =66;
arr = add(index,value,arr);
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
//往数组中指定的索引位置添加元素
public static int[] add(int index,int value, int[] arr){
/**
//方法一:将需要添加位置的值,先保存起来,循环替换,一直换到最后
for(int i = index;i<arr.length;i++){
int temp = arr[i];
arr[i]=value;
value = temp;
}*/
//方法二:先将所有位置数据往后移动,移动完之后将值赋到指定的位置
for(int i = arr.length;i>index;i--){
arr[i-1]=arr[i-1-1];
}
arr[index]=value;
return arr;
}
}
4.4-并发性修改异常
import java.util.*;
public class Demo{
public static void main(String[] args){
//创建一个对象,并添加元素
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
//创建一个迭代器,获取迭代对象
Iterator<String> it = list.iterator();
/**while(it.hasNext()){
String str = it.next();
这样写有问题,会触发并发性修改异常,因为
迭代器在获取时会获取需要迭代的集合长度,在迭代过程中
对集合长度进行修改,迭代器获取到的长度和集合元素个数
不一致,会引起异常。
但可以修改元素,不能增删
if(str.equals("bbb")){
collection.add("eee");
}
}*/
//使用增强for循环也不行,因为调用的还是迭代器方法
//只能使用普通的for循环
for(int i=0;i<list.size();i++){
if("bbb".equals(list.get(i)))
list.add("eee");
}
}
}
4.5-ListIterator
ListIterator
列表迭代器- 通过list集合的listIterator()方法获取迭代对象,因此它是List集合的专属迭代器
- 可以迭代任意方向,从前往后迭代,或者从后往前迭代;
ListIterator
常用方法
方法名 | 说明 |
---|---|
boolean next() | 返回下一个元素 |
E hasNext() | 判断集合是否存在下一个元素 |
boolean privous() | 返回上一个元素 |
E hasPrivous() | 判断集合是否存在上一个元素 |
void add(E e) | 向集合中增加元素 |
4.6-数据结构
程序=数据结构+算法
数据结构是计算机存储、组织数据的方式。指的是互相之间存在一种或者多种特定关系的数据元素的集合,经过精心的设计、选择数据结构可以让程序的运行和数据的存储提高效率。
4.6.1-栈
栈模型:先进后出、后进先出。可以理解为一个一端开口的箱子。
- 栈底元素:最先进入栈的元素
- 栈顶元素:最后进入栈的元素
- 入栈/压栈:元素进入栈的过程
- 出栈/弹栈:元素出栈的过程
模拟栈数据代码
import java.util.*;
public class Demo{
public static void main(String[] args){
speak(3);
}
public static void speak(int i){
System.out.println("我入栈了:"+i);
if(i>1)
speak(i-1);
System.out.println("我出栈了:"+i);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DhjiP2Y8-1599474241560)(file:///c:\users\public\documents\kk6%20files\kk6.0\account\3661@oakk.ukelink.com\image_cache\cb4d66f5a240417db31c4078d20a40f8.png)]
4.6.2-队列
队列模型:两端都有开口,数据像水一样从一段流向另一端,先进先出,后进后出
- 入队列:数据从后端进入队列的过程
- 出队列:数据从前端离开队列的过程
模拟队列代码
import java.util.*;
public class Demo{
public static void main(String[] args){
for(int i =1;i<10;i++)
speak(i);
}
public static void speak(int i){
System.out.println("我入队列了:"+i);
System.out.println("我出队列了:"+i);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-taF4r8N6-1599474241562)(file:///c:\users\public\documents\kk6%20files\kk6.0\account\3661@oakk.ukelink.com\image_cache\ab6e9fe7dbb44ec09977c60bf18b92c5.png)]
4.6.3-数组
相同数据类型的不可变长集合,数组的在内存中的存储空间是连续的,查询和修改快,删除和新增慢(不含数组最后一个元素),在4.3插入算法写了数组插入过程
- 数组的查询和修改,可以通过索引快速定位,效率很高
- 增加和删除的时候,需要调整修改位置之后其它元素的位置,还要考虑数组长度问题,所以效率慢
4.6.4-链表
链表相对于数组,增加和删除较快,查询和修改较慢的数据模型
-
节点:数据单元
-
数据域:用来实际存储数据的空间
-
指针域:用来存储下一个节点地址的空间
代码模拟单链表
import java.io.*; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.*; public class Osstest01 { public static void main(String[] args){ //创建一个头节点,便于以后作为标识 LinkNode headNode = new LinkNode(9527); //创建三个节点 LinkNode ln1 = new LinkNode(3); LinkNode ln2 = new LinkNode(5); LinkNode ln3 = new LinkNode(7); //将三个节点添加到头节点之后 add(ln1,headNode); add(ln2,headNode); add(ln3,headNode); //输出链表中所有节点 showAll(headNode); //求链表的有效节点长度 int j = size(headNode); System.out.println("链表长度——》"+j); //在指定的位置增加元素 LinkNode ln02 = new LinkNode(88); LinkNode ln03 = new LinkNode(97); addIn(ln1,ln02,headNode); showAll(headNode); System.out.println("======="); //修改指定的元素 change(ln02,ln03,headNode); showAll(headNode); System.out.println("======="); //删除指定节点之后的数据 del(ln02,headNode); showAll(headNode); } //删除指定的节点之后的数据 public static void del(LinkNode node,LinkNode linkNode){ //如果链表next属性为空,则只有一个节点 if(linkNode.next==null){ System.out.println("指定节点之后无数据!~"); } //当next属性不为空,则进行判断 while(linkNode.next!=null){ //如果值相等,则将该节点的指针域指向下一个节点指针域指向的地址 if(linkNode.getVal()==node.getVal()){ linkNode.next = linkNode.next.next; break; } //重置指针域,获取链表下一个元素 linkNode = linkNode.next; } } //修改指定节点数据 public static void change(LinkNode node,LinkNode node1,LinkNode linkNode){ //指针域为空,则只有当前元素 if(linkNode.next==null) node = node1; while(linkNode.next!=null){ LinkNode temp = null; linkNode = linkNode.next; if(linkNode.getVal()==node.getVal()){ // temp=node; linkNode.setVal(node1.getVal()); // linkNode.next=node.next; break; } } } //在指定的位置增加元素 public static void addIn(LinkNode node1,LinkNode node2,LinkNode linkNode){ if(node1.next==null){ node1.next=node2; } while(linkNode.next!=null){ linkNode=linkNode.next; if(linkNode.getVal()==node1.getVal()){ LinkNode temp = linkNode.next; linkNode.next = node2; node2.next=temp; break; } } } //求链表的有效节点长度 public static int size(LinkNode linkNode){ linkNode = linkNode.next; int i = 0; while(linkNode!=null){ i++; linkNode = linkNode.next; } return i; } //修改指定位置的元素 //删除一个节点数据 //输出链表的节点信息 public static void showAll(LinkNode linkNode){ linkNode = linkNode.next; while(linkNode!=null){ System.out.println(linkNode.getVal()); linkNode = linkNode.next; } } //添加元素到链表的末尾 public static void add(LinkNode addNode,LinkNode linkNode){ if(linkNode==null) linkNode=addNode; while(linkNode.next!=null){ linkNode=linkNode.next; } linkNode.next=addNode; } }
4.7-LinkedList
4.7.1-LinkedList中的常用方法
方法名 | 说明 |
---|---|
public void addFirst(E e) | 向集合开始的位置添加元素 |
public void addLast(E e) | 向集合末尾的位置添加元素 |
public E getFirst() | 获取集合开头的元素 |
public E getLast() | 获取集合末尾的元素 |
public E removeFirst() | 删除集合开头的元素 |
public E removeLast() | 删除集合末尾的元素 |
5-Set
5.1-概述
- Set是一个接口,需要通过实现类来进行操作
- Set集合下面的所有实现类,没有带索引的方法,所以不能使用下标操作,也不能使用普通for循环进行遍历。
5.2-哈希值
哈希值是JDK根据数值或者对象的地址经过计算得到的int类型的数据
5.3-HashSet
-
HashSet特点
- 底层数据结构是“哈希表”(由数组和链表组成)
- 对于集合的迭代顺序(读写顺序)不保证
- 没有索引的概念
- 不包含重复的值
-
HashSet去重原理
- 先对比hashcode的值,值相同再使用equals比较对象的内容,有任意一个不同则视为两个元素不一样。
5.4-哈希表
数组+链表
哈希值会被%16(保存到一个数组中,这个数组长度为16,值为 0~15,所有哈希值%16之后值为多少,则放到相应的数组值位置,如果前面已经存在元素,则采用链表形式添加到上一个元素之后)
5.5-LinkedHashSet
-
LinkedHashSet特点
-
它是由哈希表和链表实现的Set接口,可以保证迭代性(读写顺序一致)
-
顺序是由链表来完成的
-
由HashSet来保证元素的唯一性
-
5.6-TreeSet
- TreeSet特点
- 有序(规则有序,不是读写,是从大到小或者从小到大)
- 可以通过构造方法类确定规则
TreeSet()
:自然排序规则(升序排序)TreeSet(Comperator c)
:自定义排序规则(通过比较器实现)