目录
集合--->容器
数组:同一种类型,长度固定,不可变,每个元素都有索引,索引从0开始。
数组在实际使用时有哪些不方便?
长度不可变
1、现实中程序运行时数据量是可以改变的,需要能够满足可变的需求
2、有的时候想存储不可重复的数据,有的时候想对元素进行排序。
例:ArrayList中数组长度可自动扩容
代码
package com.ffyc.javacollection;
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add("abc");
arrayList.add("abc");
arrayList.add("abc");
arrayList.add("abc");
arrayList.add("abc");
arrayList.add("abc");
arrayList.add("bbb");
arrayList.add("ccc");
arrayList.add("abc");
arrayList.add("abc");
arrayList.remove("bbb");
System.out.println(arrayList);
}
}
运行
所以Java中为我们提供了许多不同特征的容器类
学习Java给我们提供的不同的容器类,来实现更为丰富的数据存储。
Java集合API
集合体系概述 Java的集合框架是由很多接口、抽象类、具体类组成的,都位于java.util包中。
单列集合
Collectio接口
Collection 接口-定义了存取一组对象的方法,其子接口Set和List分别定义 了存储方式。
List接口实现类
ArrayList 数组实现
概念
ArrayList<String> arrayList = new ArrayList<>();
底层数组实现,查询的效率最快
中间删除,添加的效率低
数组的空间利用率可能会浪费
代码
List接口实现类
add
ArrayList 是可以保存重复元素的,底层是数组实现,添加的元素类型可以是任意类型的
package com.ffyc.javacollection.list;
import java.util.ArrayList;
public class ArraysListDemo1 {
public static void main(String[] args) {
ArrayList alist = new ArrayList();
alist.add(1);
alist.add("c");
alist.add('c');
for (int i = 0;i<alist.size();i++){
Object object = alist.get(i);
if(object instanceof String){
String s = (String) object;
System.out.println(s.length());
}
}
}
}
运行
代码
然集合中默认是可以添加任意数据类型的,但是后续处理时,会出现类型转换问题
所以Java中 集合类都支持自定义类型(泛型 把类型当作参数传递)
ArrayList<String> 定义时为集合中可以存储的数据设计一个类型,必须是类类型
好处:一个集合中只能存储一种相同数据类型,后续处理方便了
package com.ffyc.javacollection.list;
import java.util.ArrayList;
public class ArraysListDemo1 {
public static void main(String[] args) {
ArrayList<Integer> arrayList1 = new ArrayList<>();
arrayList1.add(10);//自动装箱
ArrayList<String> arrayList2 = new ArrayList<>();
arrayList2.add("hhh");
}
}
ArrayList方法
代码
底层是一个数组,默认长度是10,当数组装满时,会自动扩容,,扩容到原来的1.5倍
package com.ffyc.javacollection.list;
import javax.net.ssl.SSLServerSocket;
import java.util.ArrayList;
public class ArraysListDemo2 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
//向末尾添加元素,会自动扩容
arrayList.add("hhh");
arrayList.add("iii");
arrayList.add("jjj");
arrayList.add("sss");
arrayList.add("kkk");
arrayList.add("hhh");
arrayList.add("iii");
arrayList.add("jjj");
arrayList.add("kkk");
arrayList.add("hhh");
arrayList.add("iii");
arrayList.add("jjj");
arrayList.add("kkk");
//向指定的位置添加元素,位置从0开始 到size(实际装入的元素个数)
arrayList.add(11,"sss");
System.out.println(arrayList);
//根据元素的内容删除数据,只删除匹配的第一个元素
arrayList.remove("sss");
System.out.println(arrayList);
//删除并返回指定位置上元素
String s = arrayList.remove(10);
System.out.println(s);
System.out.println(arrayList);
//是否包含指定元素
System.out.println(arrayList.contains("hhh"));
//获取指定位置的元素(底层时数组,获取元素的速度是最快的)
System.out.println(arrayList.get(3));
//获取指定元素首次出现的位置
System.out.println(arrayList.indexOf("jjj"));
//从后开始查找
System.out.println(arrayList.lastIndexOf("hhh"));
//判断集合中的元素是否为空 为空--->true 否则--->false
System.out.println(arrayList.isEmpty());
//替换指定位置的元素
System.out.println(arrayList.set(1, "ccc"));
//返回数组的实际(装有元素)长度(个数)
System.out.println(arrayList.size());
System.out.println(arrayList);
//清空集合
arrayList.clear();
System.out.println(arrayList);
}
}
运行
LinkedList 链表实现
概念
LinkedList<String> linkedlist = new LinkedList<>();
查询慢
中间增加和删除速度快,元素不需要移动,只需要改变地址值
不存在空间浪费
代码
List接口实现类
LinkedList
底层是链表实现,每一个数据封装在一个Node对象中。
package com.ffyc.javacollection.list;
import java.util.LinkedList;
public class LInkedListDemo {
public static void main(String[] args) {
LinkedList<String> linkedlist = new LinkedList<>();
linkedlist.add("a");
linkedlist.add("b");
linkedlist.add("c");
linkedlist.add("d");
//向链表末尾添加元素
linkedlist.add("d");
//向指定的位置添加元素
linkedlist.add(2, "e");
System.out.println(linkedlist);
//从链表中获取指定位置的元素(从头或者尾开始查找,效率低于ArrayList)
System.out.println(linkedlist.get(3));
System.out.println(linkedlist.contains("b"));
System.out.println(linkedlist.remove("a"));
System.out.println(linkedlist.remove(2));
//删除并返回第一个结点内容
System.out.println(linkedlist.removeFirst());
//删除并返回最后一个结点内容
System.out.println(linkedlist.removeLast());
System.out.println(linkedlist.isEmpty());
System.out.println(linkedlist.size());
linkedlist.set(1, "s");
System.out.println(linkedlist);
//清空
linkedlist.clear();
System.out.println(linkedlist);
}
}
运行
Vector 数组实现
概念
Vector<Integer> vector = new Vector<>();
代码
Vector
数组实现
是多线程安全的
package com.ffyc.javacollection.list;
import java.util.Vector;
public class VectorDemo {
public static void main(String[] args) {
Vector<Integer> vector = new Vector<>();
vector.add(1);
vector.add(2);
vector.add(3);
vector.add(4);
vector.add(1);
vector.add(1);
vector.add(1);
vector.add(1);
vector.add(1);
vector.add(1);
vector.add(1);
System.out.println(vector);
}
}
运行
List接口集合迭代
for循环
代码
package com.ffyc.javacollection.list;
import java.util.ArrayList;
public class ArraysListDemo3 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("a");
arrayList.add("a");
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.add("d");
arrayList.add("e");
arrayList.add("f");
//1、for循环
for (int i = 0; i < arrayList.size(); i++) {
if(arrayList.get(i).equals("a")){
//for循环的时候,是支持从for循环中删除元素的,但是删除后,后面的元素会向前移动,需要控制索引
arrayList.remove(i);
i--;
}
}
System.out.println(arrayList);
}
}
运行
增强for循环
增强for循环中不可进行删除元素,不能使用remove(),使用会报错
代码一
package com.ffyc.javacollection.list;
import java.util.ArrayList;
public class ArraysListDemo3 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("a");
arrayList.add("a");
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.add("d");
arrayList.add("e");
arrayList.add("f");
//2、增强for循环
for(String s:arrayList){
if(s.equals("a")){
arrayList.remove("a");//增强for循环时,删除元素的过程中不允许删除元素
}
}
System.out.println(arrayList);
}
}
代码二
package com.ffyc.javacollection.list;
import java.util.ArrayList;
public class ArraysListDemo3 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("a");
arrayList.add("a");
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.add("d");
arrayList.add("e");
arrayList.add("f");
//增强for循环l 方式1:根据键找值
for(String s:arrayList){
System.out.println(s);
}
}
}
运行
迭代器一
代码
package com.ffyc.javacollection.list;
import java.util.ArrayList;
import java.util.Iterator;
public class ArraysListDemo3 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("a");
arrayList.add("a");
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.add("d");
arrayList.add("e");
arrayList.add("f");
//迭代器1
Iterator<String> it = arrayList.iterator();
while(it.hasNext()){
String n = it.next();
if(n.equals("a")){
it.remove();//迭代器中删除的方法,底层有一计数器,删除元素时,计数器会自动的回退
}
}
System.out.println(arrayList);
}
}
运行
迭代器二
ListIterator():默认是从第0个位置开始的,只能从前向后遍
ListIterator(index):从指定的位置开始向前/向后遍历
代码
package com.ffyc.javacollection.list;
import java.util.ArrayList;
import java.util.ListIterator;
public class ArraysListDemo3 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("a");
arrayList.add("a");
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.add("d");
arrayList.add("e");
arrayList.add("f");
ListIterator<String> listIterator = arrayList.listIterator(arrayList.size());//size = 最大索引+1
while(listIterator.hasPrevious()){
String s = listIterator.previous();
System.out.println(s);
}
}
}
运行
set接口
HashSet
概念
HashSet<Student> stu = new HashSet<>();
底层使用的是HashMap
元素存储是无序的
去除重复元素的方式
hashCode() equals()
代码
Set接口:不能存储重复元素
HashSet
元素是无序的(既不是添加顺序,也不是按元素的自然顺序)
package com.ffyc.javacollection.set;
import java.util.HashSet;
public class HashSetDemo1 {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("a");
set.add("x");
set.add("p");
set.add("k");
set.add("i");
set.add("e");
set.add("p");
System.out.println(set);
System.out.println(set.contains("a"));
System.out.println(set.isEmpty());
set.remove("p");
System.out.println(set);
System.out.println(set.size());
set.clear();
System.out.println(set);
}
}
运行
代码
向HashSet中是添加元素时,是如何判断元素是否重复的
添加元素时 调用equals()判断,效率低(一个一个字符判断)
底层用到HsahCode() 和 equals() 方法
puwvzwogvc 用内容计算一个hash值(整数),用hash值比较速度快
但是hash是不安全的,有可能内容不同,计算的hash值相同
当hash值相同时,调用equals方法,判断内容是否相等
这样效率提高了 也保证安全了
package com.ffyc.javacollection.set;
import java.util.HashSet;
public class HashSetDemo2 { public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("a");
set.add("x");
set.add("puwvzwogvc");//500
set.add("通话");
set.add("重地");
set.add("e");
set.add("puwvzwogvc");//500
System.out.println(set);
}
}
运行
HashSet自定义类型
代码
package com.ffyc.javacollection.set;
public class Student extends Object implements Comparable<Student>{
private int num;
private String name;
public Student(int num, String name) {
this.num = num;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (num != student.num) return false;
return name.equals(student.name);
}
@Override
public int hashCode() {
int result = num;
result = 31 * result + name.hashCode();
return result;
}
@Override
public String toString() {
return "Student{" +
"num=" + num +
", name='" + name + '\'' +
'}';
}
}
添加时,判断时会调用类中hashCode()计算hash值,类中没有hashCode(),会调用父类hashCode()
Object类中的public native int hashCode();native本地方法(操作系统提供的)
所以只要是new出来的,调用Object类中hash值,是内容地址,肯定不相同
如果我们想要对象中的内容相等就判定为重复元素,就必须在我们的类中重写hashCode() equals() 用对象中的内容来计算hash值
package com.ffyc.javacollection.set;
import java.util.HashSet;
public class HashSetDemo3 {
public static void main(String[] args) {
HashSet<Student> stu = new HashSet<>();
Student stu1 = new Student(001, "钟白");
Student stu2 = new Student(002, "逸帆");
Student stu3 = new Student(003, "路先生");
Student stu4 = new Student(001, "钟白");
stu.add(stu1);
stu.add(stu2);
stu.add(stu3);
stu.add(stu4);
System.out.println(stu);
}
}
运行
TreeSet
概念
TreeSet<Integer> tset = new TreeSet<>();
树型结构
有序(是根据值的自然顺序排序)
去重 排序使用的是compareTo()
代码
Set 不能存储重复元素
TreeSet
底层是树型结构 有一个根节点,每一个结点有两个子节点,大的元素向右放,小的元素向左放
添加进来的元素可以排序(有序的 不是添加的顺序,是元素的自然顺序)
package com.ffyc.javacollection.set;
import java.util.TreeSet;
public class TreeSetDemo1 {
public static void main(String[] args) {
TreeSet<Integer> tset = new TreeSet<>();
tset.add(3);
tset.add(1);
tset.add(5);
tset.add(4);
tset.add(3);
tset.add(2);
tset.size();
tset.contains(2);
//删除并返回第一个元素
System.out.println(tset.first());
tset.isEmpty();
//删除指定内容的一个元素
tset.remove(3);
//删除并返回最后一个元素
System.out.println(tset.pollLast());
System.out.println(tset);
tset.clear();
System.out.println(tset);
}
}
运行
TreeSet自定义类型
代码
package com.ffyc.javacollection.set;
public class Student extends Object implements Comparable<Student>{
private int num;
private String name;
public Student(int num, String name) {
this.num = num;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"num=" + num +
", name='" + name + '\'' +
'}';
}
/*
提供的排序比较的方法
*/
@Override
public int compareTo(Student o) {
return this.num-o.num;
}
}
package com.ffyc.javacollection.set;
import java.util.TreeSet;
public class TreeSetDemo2 {
public static void main(String[] args) {
TreeSet<Student> tset = new TreeSet<>();
Student stu1 = new Student(001, "钟白");
Student stu2 = new Student(002, "逸帆");
Student stu3 = new Student(003, "路先生");
Student stu4 = new Student(001, "钟白");
tset.add(stu2);
tset.add(stu4);
tset.add(stu3);
tset.add(stu1);
System.out.println(tset);
}
}
运行
Set接口集合迭代
Set接口集合是有序的,没有下标,无法使用for循环,其他与collenction一致
遍历方式
增强for循环
迭代器遍历
Collection接口
Collection 接口-定义了存取一组对象的方法,其子接口Set和List分别定义 了存储方式。
Collections类
Collections是集合类的工具类,与数组的工具类Arrays类似
代码
集合工具类
package com.ffyc.javacollection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class CollenctionsDemo {
public static void main(String[] args) {
ArrayList<Integer> arrayList1 = new ArrayList<>();
arrayList1.add(1);
arrayList1.add(5);
//把一个数组添加到集合中
Collections.addAll(arrayList1,3,7,2,6 );
//排序
Collections.sort(arrayList1);
//二分查找(必须有序)如果找到,返回元素所在位置
System.out.println(Collections.binarySearch(arrayList1, 1));
//交换位置
Collections.swap(arrayList1, 3, 1);
System.out.println(arrayList1);
//逆序
Collections.reverse(arrayList1);
System.out.println(arrayList1);
//随机顺序排放
Collections.shuffle(arrayList1);
System.out.println(arrayList1);
//填充 集合中的元素全部一致化
Collections.fill(arrayList1, 1);
System.out.println(arrayList1);
ArrayList<Integer> arrayList2 = new ArrayList<>();
arrayList2.add(1);
arrayList2.add(3);
//把第二个参数的集合元素复制到第一个集合参数的集合中,第一个集合的size必须大于等于第二个集合size
Collections.copy(arrayList1, arrayList2);
System.out.println(arrayList2);
System.out.println(arrayList1);
}
}
运行
可变参数
类型 ... 参数名 可变长度的参数,本质是数组
一个参数列表中,只能有一个可变长度的参数,而且必须放在参数列表的末尾
代码
package com.ffyc.javacollection;
import java.util.Arrays;
public class CollenctionsDemo {
public static void main(String[] args) {
test(1,2,3);
}
public static void test(int b,int ...a){
System.out.println(Arrays.toString(a));
}
}