集合
集合的概念
-
概念:对象的容器,定义了多个对象进行操作的常用方法。可以实现数组的功能
-
和数组的区别
- 数组长度固定,集合长度不固定
- 数组可以存储基本类型和引用类型,集合只能存储引用类型
-
位置:java.util.*
Collection集合

Collection父接口
-
特点:代表一组任意类型的对象,无需、无下标、不能重复
-
实例1
package chapter01;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Demo01 {
/*
Collection接口的使用
(1)添加元素
(2)删除元素
(3)遍历元素
(4)判断
*/
public static void main(String[] args) {
//创建集合
Collection collection=new ArrayList();
//添加元素
collection.add("苹果");
collection.add("西瓜");
collection.add("香蕉");
System.out.println("元素个数:"+collection.size());
System.out.println(collection);
//删除元素
collection.remove("香蕉");
System.out.println("删除之后个数:"+collection.size());
//遍历元素
//1.增强for循环遍历(无下标)
for (Object object: collection
) {
System.out.println(object);
}
//2.使用迭代器遍历(迭代器专用于遍历集合)
Iterator it = collection.iterator();
/*
Iterator包含三个方法
hasNext() 有没有下一个元素
next() 获取下一个元素
remove() 删除当前元素
迭代时不可同时使用collection.remove删除操作,会出现并发修改错误
使用it.remove删除
*/
while (it.hasNext()) {//还有下一个元素
Object object1 = it.next();//取出下一个元素
System.out.println(object1);
}
//判断
System.out.println(collection.contains("西瓜"));
System.out.println(collection.isEmpty());
}
}
- 实例2
package chapter01;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Demo02 {
/*
Collection的使用:保存学生信息
*/
public static void main(String[] args) {
//新建collection对象
Collection collection = new ArrayList();
Student st1=new Student("张三",20);
Student st2=new Student("李四",18);
Student st3=new Student("王五",16);
//添加数据
collection.add(st1);
collection.add(st2);
collection.add(st3);
System.out.println("元素个数:"+ collection.size());
System.out.println(collection.toString());
//2.删除数据
collection.remove(st2);
System.out.println("删除之后:"+ collection.size());
//clear清除集合中存储的对象的地址,并不是在堆中删除对象
//collection.clear();
//3.遍历
//增强for遍历
for (Object object : collection
) {
Student s = (Student)object;
System.out.println(s.toString());
}
//迭代器遍历
Iterator it = collection.iterator();
while (it.hasNext()){
Student ss = (Student) it.next();
System.out.println(ss.toString());
}
//4.判断
System.out.println(collection.contains(st1));
System.out.println(collection.contains(new Student("zhangsan",20)));
}
}
package chapter01;
/**
*学生类
*
*/
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ",age=" + age + "]";
}
}
List子接口
-
特点:有序(添加和获取时)、有下标、元素可重复
-
实例
package chapter01;
import java.util.*;
/**
* List接口的使用
* 特点:
* ①有序有下标
* ②可以重复
*/
public class Demo03 {
public static void main(String[] args) {
//创建集合对象(实例化子类arrayList)
List list = new ArrayList<>();
//1.添加元素
list.add("RedMi");
list.add("HaWei");
list.add(0,"iPhone");
System.out.println("元素个数"+list.size());
System.out.println(list.toString());
//2.删除元素
list.remove("iPhone");
//根据下标删除:list.remove(0);
System.out.println(list.toString());
//3.遍历
//3.1有下标支持for
for (int i = 0; i <list.size() ; i++) {
//根据下标获取元素,返回object类型:list.get(i)
System.out.println(list.get(i));
}
//3.2增强for
for (Object object: list
) {
System.out.println(object);
}
//3.3迭代器遍历
Iterator it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//3.4列表迭代器遍历,功能更为强大更为灵活
//1.可以向前或向后遍历
//2.可以添加删除修改元素
ListIterator lit = list.listIterator();
//正向遍历
while (lit.hasNext()){
System.out.println(lit.nextIndex() +":"+ lit.next());
}
//逆向遍历
while (lit.hasPrevious()){
System.out.println(lit.previousIndex() +":"+ lit.previous());
}
//4.判断
//是否存在
System.out.println(list.contains("RedMi"));
//是否为空
System.out.println(list.isEmpty());
//5.获取位置
System.out.println(list.indexOf("RedMi"));
}
}
- 实例2:
package chapter01;
import java.util.ArrayList;
import java.util.List;
public class Demo04 {
public static void main(String[] args) {
List list = new ArrayList();
//添加数字
//添加数字隐含自动装箱
list.add(20);
list.add(30);
list.add(40);
list.add(50);
list.add(60);
System.out.println("元素个数"+list.size());
System.out.println(list.toString());
//删除操作
//报错IndexOutOfBoundsException:list.remove(20);
list.remove((Object)20);
System.out.println("删除元素"+list.size());
//subList方法:返回子集合含头不含尾
List subLIst = list.subList(1,3);
System.out.println(subLIst);
}
}
List实现类
ArrayList
- 数组结构实现,查询快、增删慢
- JDK1.2版本,运行效率快、线程不安全
源码分析
-
默认容量:DEFAULT_CAPACITY = 10,如果集合中没有添加元素,容量为零,每次扩容大小均为原来的1.5倍
-
存放元素的数组:elementData
-
实际元素个数:size
-
add( )方法:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)//不成立
newCapacity = hugeCapacity(minCapacity);//不会执行
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
- 实例
package chapter01;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
/**
* ArrayList的使用
* 存储结构:数组
*
*/
public class Demo05 {
public static void main(String[] args) {
//创建集合
ArrayList arrayList = new ArrayList<>();
//1.添加元素
Student s1= new Student("刘德华",20);
Student s2= new Student("王子龙",20);
Student s3= new Student("张继宝",20);
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
System.out.println(arrayList.size());
System.out.println(arrayList.toString());
//2.删除元素
arrayList.remove(new Student("刘德华",20));
/*
若要使用arrayList.remove(new Student("刘德华",20));
则要重写equals方法:比较名字和年龄,不比较地址
@Override
public boolean equals(Object obj) {
//判断是不是同一对象
if(this == obj){
return true;
}
//判断是否为空
if (obj==null){
return false;
}
//判断是否是Student类型
if (obj instanceof Student){
//强制类型转换
Student s=(Student)obj;
//判断属性
if (this.name.equals(s.getName())&&this.age==getAge()){
return true;
}
}
return false;
}
}
*/
System.out.println(arrayList.size());
//3.遍历元素
//迭代器
Iterator it = arrayList.iterator();
while(it.hasNext()){
Student s =(Student)it.next();
System.out.println(s.toString());
}
//列表迭代器
ListIterator lit = arrayList.listIterator();
while(lit.hasNext()){
Student s =(Student)lit.next();
System.out.println(s.toString());
}
//逆序
while (lit.hasPrevious()){
Student s =(Student)lit.previous();
System.out.println(s.toString());
}
//4.判断
System.out.println(arrayList.contains("刘德华"));
System.out.println(arrayList.isEmpty());
}
}
Vector
- 数组结构实现,查询快、增删慢
- JDK1.0版本,运行效率慢、线程安全
package chapter02;
import java.util.Enumeration;
import java.util.Vector;
public class Demo01 {
public static void main(String[] args) {
Vector vector = new Vector<>();
//添加元素
vector.add("苹果");
vector.add("香蕉");
vector.add("橘子");
//遍历
//枚举器遍历
Enumeration en = vector.elements();
while(en.hasMoreElements()){
String o = (String) en.nextElement();
System.out.println(o);
}
//删除
vector.remove(0);
System.out.println(vector.toString());
//判断
System.out.println(vector.contains("西瓜"));
System.out.println(vector.isEmpty());
}
}
LinkList
- 链表结构实现(双向链表),增删快、查询慢
ArrayList和LinkList的区别:不同结构实现
泛型
- java泛型其本质是参数化类型,把类型作为参数来传递
- 常见形式有泛型类、泛型接口、泛型方法
- 语法:
- <T,... > T(大写字母就可)称为类型占位符,表示一种引用类型
- 好处:
- 提高代码的重用性
- 防止类型转换的异常,提高代码的安全性
- 测试类
package generic;
public class TestGeneric {
public static void main(String[] args) {
//使用泛型类创建对象
//1.泛型只能是引用类型
//2.不同的泛型类型的对象之间不能相互复制
MyGeneric<String> myGeneric = new MyGeneric<String>();
myGeneric.t="hello";
myGeneric.show("我爱学习");
String string = myGeneric.getT();
MyGeneric<Integer> myGeneric1 = new MyGeneric<Integer>();
myGeneric1.t = 100;
myGeneric1.show(200);
Integer integer = myGeneric1.getT();
//泛型接口
MyInterfaceImpl01 myInterface01 = new MyInterfaceImpl01();
myInterface01.server("张三");
//泛型方法
MyGenericMethod myGenericMethod = new MyGenericMethod();
//类型由传递的数据的类型决定
myGenericMethod.show("张三");
myGenericMethod.show200);
//
}
}
泛型类
package generic;
/**
* 泛型类
* 语法:类名<T,...>
* T:是类型占位符,表示一种引用类型,多个则逗号隔开
*
* @author zqh
*/
public class MyGeneric<T> {
//使用泛型T
//不能实例化直接创建对象(eg.私有构造方法)
//1.创建变量
T t;
//2.作为方法参数
public void show(T t) {
System.out.println(t);
}
//3.作为方法的返回值
public T getT() {
return t;
}
}
泛型接口
package generic;
/**
* 泛型接口
* 语法:接口名<T>
* 不能创建泛型静态常量
*/
public interface MyInterface<T> {
T server(T t);
}
package generic;
//创建对象的时候再确定
public class MyInterfaceImpl01<T> implements MyInterface<T>{
@Override
public T server(T t) {
System.out.println(t);
return null;
}
}
泛型方法
package generic;
/**
* 泛型方法
* 语法:<T> 返回值类型
*/
public class MyGenericMethod {
//泛型方法
//使用范围仅在该方法
public <T> T show(T t){
System.out.println("泛型方法"+t);
return t;
}
}
泛型集合
-
概念:参数化类型、类型安全的集合,强制集合的类型必须一致
-
特点:
- 编译时即可检查,而非运行时抛出异常
- 访问时,不必类型转换(拆箱)
- 不同泛型之间引用不能相互赋值,泛型不存在多态
package generic;
import java.util.ArrayList;
public class Demo03 {
public static void main(String[] args) {
//实例化时声明数据类型
ArrayList<String> arraylist = new ArrayList<>();
arraylist.add("xxx");
arraylist.add("yyy");
//arraylist.add(10);
//arraylist.add(20);
for (Object object:arraylist
) {
String str= (String) object;
System.out.println(str);
}
}
}
Set子接口
- 特点:无序、无下标、元素不可重复
package chapter03;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* Set接口的使用
* 特点:
* ①无序、无下标
* ②不能重复
*/
public class Demo01 {
public static void main(String[] args) {
//创建集合
Set<String> set = new HashSet<>();
//添加数据
set.add("xiaomi");
set.add("huawei");
set.add("pingguo");
set.add("xiaomi");
System.out.println("数据个数"+set.size());
System.out.println(set.toString());
//删除
set.remove("xiaomi");
//遍历
//增强for遍历
for (String string:set
) {
System.out.println(string);
}
//迭代器遍历
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//判断
set.contains("huawei");
set.isEmpty();
}
}
Set实现类
HashSet
- 基于hashCode计算元素存放位置
- 当存入元素的哈希码相同时,会调用equals进行确认,如果结果为true,则拒绝后者写入
package chapter03;
import java.util.HashSet;
import java.util.Iterator;
/**
* HashSet集合的使用
*存储结构:哈希表
*/
public class Demo02 {
public static void main(String[] args) {
//创建集合
HashSet<String> hashSet = new HashSet<>();
//添加元素
hashSet.add("liudehua");
hashSet.add("zhangsan");
hashSet.add("lisi");
hashSet.add("liudehua");
System.out.println(hashSet.size());
System.out.println(hashSet.toString());
//删除元素
hashSet.remove("liudehua");
//遍历
//foreach遍历
for (String string: hashSet
) {
System.out.println(string);
}
//迭代器
Iterator<String> iterator = hashSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//判断
hashSet.contains("zhangsan");
hashSet.isEmpty();
}
}
package chapter03;
/**
* 存储过程(重复依据):
* 1.根据hashCode计算保存的位置,如果此位置为空则直接保存,如果不为空执行第二步
* 2.执行equals方法,如果equals方法为true,则认为是重复,否则形成链表
*
* 避免存储相同数据则需重写hashCode方法和equals方法
*/
import java.util.HashSet;
import java.util.Iterator;
public class Demo03 {
public static void main(String[] args) {
//创建集合
HashSet<Person> person = new HashSet<>();
//添加元素
Person p1 = new Person("zhangsan",20);
Person p2 = new Person("lisi",20);
Person p3 = new Person("wangwu",20);
person.add(p1);
person.add(p2);
person.add(p3);
//重写方法后无法插入相同数据
person.add(new Person("wangwu",20));//添加失败
System.out.println("元素个数"+person.size());
System.out.println(person.toString());
//删除
person.remove(p1);
//遍历
//foreach遍历
for (Person per: person
) {
System.out.println(per);
}
//迭代器遍历
Iterator it = person.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}
package chapter03;
import java.util.Objects;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ",age=" + age + "]";
}
//也可以idea自动生成代码
@Override
public int hashCode() {
int n1= this.name.hashCode();
int n2 = this.age;
return n1+n2;
}
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj==null){
return false;
}
if (obj instanceof Person){
Person p = (Person)obj;
if (this.name.equals(p.getName())&&this.age==p.getAge()){
return true;
}
}
return false;
}
}
TreeSet
-
基于排列顺序实现元素不重复
-
实现了SortedSet接口,对集合元素自动排序
-
元素对象的类型必须实现Comparable接口,制定排序规则
-
通过CompareTo方法是否为重复元素
-
实例一
package chapter03;
import java.util.Iterator;
import java.util.TreeSet;
/**
* TreeSet的使用
* 存储结构:红黑树
*
*/
public class Demo04 {
public static void main(String[] args) {
//创建集合
TreeSet<String> treeSet = new TreeSet<>();
//添加元素
treeSet.add("xyz");
treeSet.add("abc");
treeSet.add("hello");
//输出时按序输出
System.out.println(treeSet.toString());
//删除
treeSet.remove("xyz");
System.out.println(treeSet.toString());
//遍历
//foreach遍历
for (String string :treeSet
) {
System.out.println(string);
}
//迭代器
Iterator<String> it=treeSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//判断
System.out.println(treeSet.contains("xyz"));
System.out.println(treeSet.isEmpty());
}
}
- 实例二
public class Person implements Comparable<Person>{
private String name;
private int age;
@Override
public int compareTo(Person o) {
int n1 =this.getName().compareTo(o.getName());
int n2 =this.age-o.getAge();
//先比姓名再比年龄
//姓名相同,n1为零
return n1==0?n2:n1;
}
//......
}
package chapter03;
import java.util.TreeSet;
/**
* 使用TreeSet保存数据
* 存储结构:红黑树
* 要求:元素必须要实现Comparable接口,
* compareTo方法返回值为零,则认为是重复元素
*/
public class Demo05 {
public static void main(String[] args) {
//创建集合
TreeSet<Person> person = new TreeSet<>();
//添加元素
Person p1= new Person("abc",20);
Person p2= new Person("bcd",20);
Person p3= new Person("cde",30);
Person p4= new Person("abc",25);
Person p5= new Person("abc",25);
person.add(p1);
person.add(p2);
person.add(p3);
person.add(p4);
person.add(p5);
System.out.println(person.toString());
}
}
Comparator接口
package chapter03;
import sun.reflect.generics.tree.Tree;
import java.util.Comparator;
import java.util.TreeSet;
/**
* TreeSet集合的使用
* COmparator:实现定制比较
* Comparable:可比较的
*
*/
public class Demo06 {
public static void main(String[] args) {
//创建集合,指定比较规则
TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>(){
@Override
public int compare(Person o1, Person o2) {
int n1= o1.getAge()-o2.getAge();
int n2=o1.getName().compareTo(o2.getName());
return n1==0?n2:n1;
}
});
Person p1= new Person("abc",20);
Person p2= new Person("bcd",20);
Person p3= new Person("cde",15);
persons.add(p1);
persons.add(p2);
persons.add(p3);
System.out.println(persons.toString());
}
}
TreeSet案例
package chapter03;
import java.util.Comparator;
import java.util.TreeSet;
/**
* 要求:使用TreeSet集合实现字符串按照长度进行排序
* helloworld zhang lisi wangwu beijing xian nanjing
*
*
*
*/
public class Demo07 {
public static void main(String[] args) {
//创建集合,指定比较规则
TreeSet<String> treeset = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int n1 = o1.length()-o2.length();
int n2 = o1.compareTo(o2);
return n1==0?n2:n1;
}
});
//添加数据
treeset.add("xian");
treeset.add("helloworld");
treeset.add("zhangsan");
treeset.add("lisi");
treeset.add("wangwu");
treeset.add("beijing");
treeset.add("nanjing");
System.out.println(treeset.toString());
}
}
Map集合
- Map接口的特点
- 用于存储任意键值对(key-value)
- 键:无序无下标不允许重复
- 值:无序无下标允许重复
Map父接口
- 特点:存储一对数据,无序无下标,键不可重复,值可重复
- 方法:
- V put(K key, V value) //将对象存入到集合中,关联键值,key重复则覆盖原值
- Object get(Object key) //根据键值获取对应的值
- Set
//返回所有的Key - Collection
values() //返回包含所有值的Collection集合 - Set<Map.Entry<K,V>> //兼职匹配的Set集合
package chapter04;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* map接口的使用
* 特点:存储键值对
* 键不能重复,值可以重复
* 无序
*/
public class Demo01 {
public static void main(String[] args) {
//创建Map集合
Map<String,String> map = new HashMap<>();
//添加元素
map.put("cn","中国");
map.put("usa","美国");
map.put("uk","英国");
map.put("cn","华夏超级牛逼大中国");//键相同,覆盖前面的中国
System.out.println("元素个数:"+map.size());
System.out.println(map.toString());
//删除元素
map.remove("usa");
System.out.println(map.toString());
//遍历
//1.使用keySet()方法,返回set集合
//Set<String> keySet = map.keySet();---与增强for合并
for (String key:map.keySet()//遍历键值
) {
System.out.println(key+map.get(key));
}
//2.使用entrySet()方法,返回一个entry类型的“键值对”
Set<Map.Entry<String,String>> entries = map.entrySet();
for (Map.Entry<String,String> entry:entries
) {
System.out.println(entry.getKey()+entry.getValue());
}
//判断
System.out.println(map.containsKey("uk"));
System.out.println(map.containsValue("英国"));
}
}
Map实现类
HashMap
-
线程不安全,效率高,键值对允许为空
-
无参构造方法默认初始容量为16,默认加载因子为0.75
package chapter04;
import chapter04.Student;
import java.util.HashMap;
import java.util.Map;
/**
* HashMap集合的使用
* 存储结构:哈希表(数组、链表、红黑树)
* 重复依据:使用key的hashCode和equals
*/
public class Demo02 {
public static void main(String[] args) {
//创建集合
HashMap<Student,String> student=new HashMap<Student,String>();
//添加元素
Student s1 = new Student("张三",100);
Student s2 = new Student("李四",101);
Student s3 = new Student("王五",102);
student.put(s1,"西安");
student.put(s2,"北京");
student.put(s3,"上海");
//可以添加,去重需要重写hashCode和equals
student.put(new Student("王五",102),"上海");
System.out.println(student.size());
System.out.println(student.toString());
//删除
student.remove(s1);
//遍历
//1.使用keySet()方法
for (Student key:student.keySet()
) { System.out.println(key.toString()+student.get(key));
}
//2.使用entrySet()方法
for (Map.Entry<Student,String> entry: student.entrySet()
) {
System.out.println(entry.getKey()+entry.getValue());
}
//判断
System.out.println(student.containsKey(s2));
}
}
HashMap源码分析
- 属性
//数组默认初始容量大小
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //16
//数组最大容量大小
static final int MAXIMUM_CAPACITY = 1 << 30;
//默认最大加载因子(达到75%扩容)
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//链地址处理冲突,链长度大于8(数组长度大于64)时,链调整为红黑树
static final int TREEIFY_THRESHOLD = 8;
static final int MIN_TREEIFY_CAPACITY = 64;
//红黑树元素个数小于6,红黑树调整为链表
static final int UNTREEIFY_THRESHOLD = 6;
HashTable
-
线程安全、运行效率慢,不允许null作为key或者value
-
子类Properties,要求key和value都是String
TreeMap
- 实现了SortedMap接口,可以对key自动排序
Collections工具类
- 概念:集合工具类,定义了除了存取以外集合常用的方法
- reverse(List<?> list) //反转集合中元素的顺序
- shuffle(List<?> list) //随机重置集合元素的顺序
- sort(List
list) //升序排序(元素类型必须实现Comparable接口)
package chapter04;
import java.util.*;
public class Demo03 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(20);
list.add(15);
list.add(6);
list.add(10);
list.add(3);
//排序
Collections.sort(list);
System.out.println(list.toString());
//binarySearch二分查找
int i = Collections.binarySearch(list,15);
System.out.println(i);
//copy复制
List<Integer> list1 = new ArrayList<>();
//(目标,源)
for (int j = 0; j <list1.size() ; j++) {
list1.add(0);
}
Collections.copy(list1,list);
System.out.println(list1.toString());
//reverse反转
Collections.reverse(list);
//shuffle打乱
Collections.shuffle(list);
//转成数组
Integer[] arr = list.toArray(new Integer[0]);
//数组转成集合
String[] names = {"张三","李四","王五"};
List<String> list2 = Arrays.asList(names);//受限集合:不能添加和删除
}
}