1.collection接口
java.util.collection接口
所有单列集合的最顶层接扣,里面定义了所有单列集合共性的方法
任意的单列集合都可以使用collection接口中的方法
1.概念
- 数组可以存放基本类型,也可以存放对象
- 集合只能存储对象 如:Arraylist
- 数组的长度不可变,集合的长度可以随意增加减少
2.集合的框架

- 单列集合的体系框架

- collection集合常用方法
(1) boolean add(E e) 确保此 collection 包含指定的元素(可选操作)。
(2) void clear() 移除此 collection 中的所有元素(可选操作)。
(3)boolean contains(Object o) 如果此 collection 包含指定的元素,则返回 true。
(4)boolean isEmpty() 如果此 collection 不包含元素,则返回 true。
(5)boolean remove(Object o) 从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
(6) int size() 返回此 collection 中的元素数。
(7)Object[] toArray() 返回包含此 collection 中所有元素的数组。
//创建集合对象,可以使用多态
Collection<String> coll = new ArrayList<>();
coll.add("hello");
//返回值是一个Boolean值,所以不用接收
coll.add("world");
coll.add("java");
// System.out.println(coll);//[hello, world, java]
// coll.remove("hello");
// System.out.println(coll);//[world, java]
// coll.clear();
// System.out.println(coll);//[]
// boolean flag = coll.contains("java");
// System.out.println(flag);//true
boolean flag2 = coll.isEmpty();
System.out.println(flag2);//false
int size = coll.size();
System.out.println(size);//3
Object[] array = coll.toArray();//将集合改为数组
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}//hello world java
2.iterator接口
java.util.iterator接口(迭代器):对集合进行遍历
collection接口中没有索引,不能使用循环遍历,所以要使用迭代器遍历
1.概念
迭代:即collection集合元素的通用获取方式。在取元素之前先判断集合中有没有元素,如果有,就把这个元素取出来,继续再判断,如果还有就继续取出来。一直把集合中的所有元素全部取出来。这种取出方式专业术语称为迭代。
2.iterator接口的常用方法
boolean hasNext() 如果仍有元素可以迭代,则返回 true。
E next() 返回迭代的下一个元素。
3.迭代器的使用
- 迭代器是一个接口,无法直接创建对象使用,需要获取iterator迭代器的实现类对象,获取实现类的方式特殊
- collection接口中有一个方法:Iterator iterator() 返回在此 collection 的元素上进行迭代的迭代器。
- 使用步骤(重点):
(1)使用集合中的iterator()获取迭代器的实现类对象,使用iterator接收(多态)
(2)使用iterator接口中的hasnext()判断是否有下一个元素
(3)使用iterator接口中的next()取出集合中的下一个元素 - 迭代器的代码实现
Collection<String> coll = new ArrayList<>();
coll.add("hello");
coll.add("world");
coll.add("java");
Iterator<String> ite = coll.iterator();
while(ite.hasNext()){
System.out.println(ite.next());
}
- 迭代器的实现原理

4.增强for循环
- 概念:底层使用的是迭代器,使用for循环的格式,简化了迭代器的书写,是JDK1.5之后出现的新特性
public interface Collectionextends Iterable 所有的单列集合都可以使用增强for(foreach)
public interface Iterable实现这个接口允许对象成为 “foreach” 语句的目标。 - 用处:用来遍历集合或数组
- 格式:
for(集合/数组的数据类型 变量名 : 集合名/数组名){
sout(变量名);
}
Collection<String> coll = new ArrayList<>();
coll.add("hello");
coll.add("world");
coll.add("java");
for (String s : coll){
System.out.println(s);
}
- 注意:增强for必须有被遍历的目标,目标只能是collection或数组,新式for仅仅作为遍历操作出现
3.泛型
用处:在创建对象时再确定数据类型
1.概念

2.创建集合对象,不使用泛型
- 好处:集合不是用泛型,默认的类型就是object类,可以存储任意类型
- 坏处:不安全,可能引发异常ClassCastException类型转换异常
Collection coll = new ArrayList();
coll.add("java");
coll.add(1);
for (Object o : coll) {
System.out.println(o);
//lenth方法时String类特有的,要想使用,必须将object向下转型为string类
String s = (String) o;
int length = s.length();
System.out.println(length);//Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.Integer cannot be cast to java.base/java.lang.String
}
3.创建集合对象,使用泛型
- 好处:
(1)避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型
(2)把运行期异常(代码运行之后会抛出的异常),提升到了编译期(写代码的时候) - 坏处:泛型是什么类型,只能存储什么类型
- 使用
ArrayList<String> obj = new ArrayList<>();
obj.add("sad");
//obj.add(1);//编译异常,不通过
//使用迭代器遍历集合
Iterator<String> iter = obj.iterator();
for (String s : obj) {
System.out.println(s);//sad
//不用做类型转换,直接调用string类特有的方法lenth();
int length = s.length();
System.out.println(length);//3
}
4.定义和使用含有泛型的类
在创建对象的时候,确定类型,不确定时,默认为object类
//定义类
public class GenericDemo<E> {
private E name;
public E getName() {
return name;
}
public void setName(E name) {
this.name = name;
}
}
//使用
GenericDemo obj = new GenericDemo();
obj.setName("ada");
Object name = obj.getName();
System.out.println(name);//ada
//泛型使用integer类
GenericDemo<Integer> integer = new GenericDemo<>();
integer.setName(123);
Integer name1 = integer.getName();
System.out.println(name1);//123
//泛型使用String类
GenericDemo<String> string = new GenericDemo<>();
string.setName("ad");
String name2 = string.getName();
System.out.println(name2);//ad
5.定义和使用含有泛型的方法
- 定义含有泛型的方法:泛型定义在修饰符和返回值类型之间
- 格式:
修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){
方法体;
}
- 含有泛型的方法,在调用方法时确定泛型的数据类型
- 传递什么类型的参数,泛型就是什么类型
public class GenericClass {
//创建含有泛型的方法
public <M> void Method1(M m){
System.out.println(m);
}
public static <Y> void Method2(Y y){
System.out.println("静态方法");
}
}
//使用
GenericClass obj = new GenericClass();
obj.Method1("ad");//ad
obj.Method1(123);//123
obj.Method1(true);//true
GenericClass.Method2("ad");//静态方法
6.定义和使用含有泛型的接口
- 含有泛型接口的第一种使用方式:定义实现类的时候确定泛型的类型
比如:public interface Iterator {}中的E next();方法
Scanner类实现了iterator接口,并指定接口的泛型为String,所以重写了next()方法,泛型默认为String
public final class Scanner implements Iterator
public String next() {}
//定义含有泛型的接口
public interface GenericInterface <I>{
public abstract void Method(I i);
}
//实现这个接口
public class GenericInterfaceImp1 implements GenericInterface<String> {
@Override
public void Method(String s) {
System.out.println(s);
}
}
//测试
GenericInterfaceImp1 obj = new GenericInterfaceImp1();
obj.Method("asd");//asd
- 含有泛型接口的第二种使用方式:创建对象的时候确定泛型的类型
(1)接口使用什么泛型,实现类就使用什么泛型,类跟着接口走
(2)就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型
public interface List中的 boolean add(E e);和E get(int index);方法
public class ArrayListimplements List中的 public boolean add(E e) {}和 public E get(int index) {}方法
//定义有泛型的接口
public interface GenericInterface <I>{
public abstract void Method(I i);
}
//定义实现接口的类,类依然是泛型
public class GenericInterfaceImp1<U> implements GenericInterface<U> {
@Override
public void Method(U u) {
System.out.println(u);
}
}
//测试
GenericInterfaceImp1<Integer> obj = new GenericInterfaceImp1<>();
obj.Method(13);//13
7.泛型通配符
泛型通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符
此时只能接收数据,不能往集合中存储数据
泛型的通配符:
?:代表任意的数据类型
使用方式:不能创建对象使用,只能作为方法的参数使用
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<>();
list1.add("hello");
list1.add("world");
list1.add("java");
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(1);
list2.add(3);
list2.add(2);
Method(list2);
Method(list1);
}
public static void Method(ArrayList<?> arr){
Iterator iter = arr.iterator();
while (iter.hasNext()){
//next方法,取出的元素的object,只有object可以接收任意类型的数据
Object o = iter.next();
System.out.println(o);
}
}
result:
1
3
2
hello
world
java
8.泛型通配符的上限限定和下限限定
上限限定:? extends E 代表使用的泛型只能是E的子类或本身
下限限定:? super E 代表使用的泛型只能是E的父类或本身
泛型只能用在方法的参数里,不能在创建对象的时候使用
4.数据结构
栈:先进后出
队列:先进先出
数组:查询块,增删慢。每次删除或新增一个元素,都必须重新创建一个新数组,将原数组中需要的内容复制到新数组中,并删除原数组
链表:增删块,查询慢。链表中的地址不是连续的,每次查询,都必须从头开始查




5.list集合
java.util.list接口 extends collection
1.特点:
(1)有序的集合:存储元素和取出元素的顺序是一致的(存储123,取出123)
(2)有索引:包含了一些带索引的方法
(3)允许存储重复的元素
2.list集合中常用方法(使用多态)
void add(int index, E element) 在列表的指定位置插入指定元素(可选操作)。
E get(int index) 返回列表中指定位置的元素。
E remove(int index) 移除列表中指定位置的元素(可选操作)。
E set(int index, E element) 用指定元素替换列表中指定位置的元素(可选操作)。
3.注意:
操作索引的时候,一定要防止索引越界异常
4.实现类:ArrayList和linkedlist
- java.util.ArrayList:ArrayList底层是数组,查询快,增删慢,此实现不是同步的
- java.util.LinkedList:,此实现不是同步的
linkedlist特点:
(1)底层是一个链表,增删块,查询慢
(2)里面包含了大量操作首尾元素的方法
(3)使用linkedlist集合特有的方法,不能使用多态 - linkedlist集合常见方法:
(1) void addFirst(E e) 将指定元素插入此列表的开头。
(2) void addLast(E e) 将指定元素添加到此列表的结尾。
(3) E getFirst() 返回此列表的第一个元素。
(4) E getLast() 返回此列表的最后一个元素。
(5)E pop() 从此列表所表示的堆栈处弹出一个元素。
(6) void push(E e) 将元素推入此列表所表示的堆栈。 此方法等效于 addFirst(E)。
(7) E removeFirst() 移除并返回此列表的第一个元素。
(8) E removeLast() 移除并返回此列表的最后一个元素。
(9) boolean isEmpty() 如果此集合不包含元素,则返回 true。 - list的遍历有三种:
(1)普通for循环遍历
(2)迭代器遍历
(3)增强for循环遍历
6.set集合
1.public interface Set extends Collection
2.此接口因为没有索引,接口的方法几乎和collection一样
3.set集合的特点:
(1)不允许存储重复的元素
(2)没有索引,没有带索引的方法,不能使用普通的for循环遍历
4.实现类HashSet
java.util.HashSet
public class HashSet implements Set此实现不是同步的
- 特点:
(1)不允许存储重复的元素
(2)没有索引,没有带索引的方法,不能使用普通的for循环遍历
(3)是一个无序的集合,存储元素和取出元素的顺序可能不一致
(4)底层是一个哈希表结构(查询速度非常快)
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(3);
set.add(2);
set.add(1);
System.out.println(set);//[1, 2, 3] hashset重写了tostring方法
//没有索引,不能使用普通for遍历
//迭代器遍历
Iterator<Integer> iter = set.iterator();
while (iter.hasNext()){
System.out.println(iter.next());//1 2 3 不允许存放重复元素,且无序
}
//增强for遍历
for (Integer i : set) {
System.out.println(i);
}
- 哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的地址)
- 在object类中有一个方法,可以获取对象的哈希值int hashCode() :返回该对象的哈希码值。
- hashcode()方法的源码: public native int hashCode();
- native:代表该方法调用的是本地操作系统的方法
- tostring方法的源码:
public String toString() {
return getClass().getName() + “@” + Integer.toHexString(hashCode());
}
//未重写hashcode方法情况下:
Person p1 = new Person();
int i = p1.hashCode();
System.out.println(i);//1967205423
Person p2 = new Person();
int i1 = p2.hashCode();
System.out.println(i1);//42121758
//getClass().getName() + "@" + Integer.toHexString(hashCode())
System.out.println(p1.toString());//ly.Person@75412c2f
System.out.println(p2.toString());//ly.Person@282ba1e
//在person类中重写hashcode方法情况下:
@Override
public int hashCode() {
return 1;
}
//测试
Person p1 = new Person();
int i = p1.hashCode();
System.out.println(i);//1
Person p2 = new Person();
int i1 = p2.hashCode();
System.out.println(i1);//1
//getClass().getName() + "@" + Integer.toHexString(hashCode())
System.out.println(p1.toString());//ly.Person@1
System.out.println(p2.toString());//ly.Person@1
System.out.println(p1 == p2);//false 逻辑地址一样,但实际上物理地址不一样
- String类重写了hashcode方法
String s1 = new String("asd");
String s2 = new String("asd");
System.out.println(s1.hashCode());//96882
System.out.println(s2.hashCode());//96882
System.out.println("重地".hashCode());//1179395
System.out.println("通话".hashCode());//1179395与上面的巧合
- 哈希表(hashset如何存储数据元素)

- set集合存储相同元素的原理

5.HashSet存储自定义类型的数据
set集合保证数据元素唯一:
存储的元素(string,integer,…,student,person),必须重写hashcode方法和equals方法
//hashcode方法和equals方法未重写:hashset集合可以存储相同的元素
Student stu1 = new Student("张三", 22);
Student stu2 = new Student("张三", 22);
Student stu3 = new Student("张三", 23);
System.out.println(stu1.hashCode());//1967205423
System.out.println(stu2.hashCode());//42121758
System.out.println(stu1 == stu2);//false
System.out.println(stu1.equals(stu2));//false
HashSet<Student> set = new HashSet<>();
set.add(stu1);
set.add(stu2);
set.add(stu3);
System.out.println(set);//[Student{name='张三', age=23}, Student{name='张三', age=22}, Student{name='张三', age=22}] 存储了相同的元素
//hashcode方法和equals方法重写后,hashset集合只能存储不同的元素
Student stu1 = new Student("张三", 22);
Student stu2 = new Student("张三", 22);
Student stu3 = new Student("张三", 23);
System.out.println(stu1.hashCode());//24022542
System.out.println(stu2.hashCode());//24022542
System.out.println(stu1 == stu2);//false
System.out.println(stu1.equals(stu2));//true
HashSet<Student> set = new HashSet<>();
set.add(stu1);
set.add(stu2);
set.add(stu3);
System.out.println(set);//[Student{name='张三', age=22}, Student{name='张三', age=23}]
6.linkedhashset集合
- public class LinkedHashSet extends HashSet
- 特点:底层是一个哈希表(数组 + 链表/红黑树) + 链表:多了一条链表(记录元素的存储顺序),保证元素有序
HashSet<String> set = new HashSet<>();
set.add("asd");
set.add("asd");
set.add("www");
set.add("asd");
set.add("com");
System.out.println(set);//[com, asd, www] 元素无序 ,不允许重复
System.out.println("----------------");
LinkedHashSet<String> linked = new LinkedHashSet<>();
linked.add("asd");
linked.add("asd");
linked.add("www");
linked.add("asd");
linked.add("com");
System.out.println(linked);//[asd, www, com] 元素有序 ,不允许重复
7.可变参数
1. 可变参数是jdk1.5之后出现的新特性
2. 使用前提:
当方法的参数类型已经确定,但参数的个数无法确定,就可以使用可变参数
3. 格式
修饰符 返回值类型 方法名(数据类型...变量名){}
4.原理
可变参数的底层就是一个数组,根据参数个数的不同,会创建不同长度的数组,来存储这些参数
传递的参数个数,可以是0个(不传递)、1个、2个、3个…多个。
5.使用
当方法的参数类型知道,但参数的个数不知道,就可以用可变参数
//main
int a = add();//创建一个长度为0的数组 new int[];
int i = add(12);//new int[]{10};
System.out.println(a);
//有可变参数的方法
public static int add(int ... arr){
System.out.println(arr);//[I@50cbc42f 底层是一个数组,类型是int
System.out.println(arr.length);//0 1
return 0;
}
注:结果中的[I@50cbc42f ,其中 [ 表示数组, I 表示整数类型,意思为整数类型的数组
//计算几个整数的和(参数不确定)
//main
int a = add();//创建一个长度为0的数组 new int[];
int i = add(12);//new int[]{10};
int i1 = add(13, 44, 55, 13, 123);
System.out.println(a);//0
System.out.println(i);//12
System.out.println(i1);//248
//有可变参数的方法
public static int add(int ... arr){
/* System.out.println(arr);//[I@50cbc42f 底层是一个数组,类型是int
System.out.println(arr.length);//0 1*/
int sum = 0;
for (int i : arr) {
sum += i;
}
return sum;
}
6.注意事项
- 一个参数列表只能有一个可变参数
- 如果方法有多个参数,可变参数必须放在参数列表的末尾
/* public static void add(String...strings,int...ints){
}*/
public static void add(int i ,double d,String s ,char...chars){
}
//可变参数的终极写法
public static void add(Object...objects){
}
//调用
add("asd",123,21.3);//任意类型都可用
8.collections工具类
1.用来对集合进行操作
2.常用方法
- static boolean addAll(Collection<? super T> c, T… elements) 将所有指定元素添加到指定 collection 中。 一次性将多个元素添加,不用之前的add();一条一条添加元素
- static void shuffle(List<?> list) 打乱集合顺序
- static void sort(List list) 根据元素的自然顺序 对指定列表按升序进行排序。
- static void sort(List list, Comparator<? super T> c) 根据指定比较器产生的顺序对指定列表进行排序。
3.注意:
- sort(List list) 使用前提:list集合中的数据类T,必须实现comparable接口,重写接口中的2. compareto方法。
- comparable接口的排序规则:
(1)自己(this)- 参数 :升序
(2)参数 - this:降序
//Student类
public class Student implements Comparable<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 +
'}';
}
@Override
public int compareTo(Student o) {
///return 0; 认为元素都是相同的
// return this.getAge() - o.getAge();//按年龄升序排
return o.getAge() - this.getAge();//按年龄降序排
}
}
//测试
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("sad",22));
Collections.addAll(list,new Student("liuying",23),new Student("liu",11));
System.out.println(list);//[Student{name='sad', age=22}, Student{name='liuying', age=23}, Student{name='liu', age=11}]
Collections.shuffle(list);//打乱顺序
System.out.println(list);//[Student{name='liu', age=11}, Student{name='liuying', age=23}, Student{name='sad', age=22}]
Collections.sort(list);
System.out.println(list);//[Student{name='liu', age=11}, Student{name='sad', age=22}, Student{name='liuying', age=23}]年龄升序排
- comparator和comparable的区别
(1)comparable:自己(this)和别人(参数)比较,自己需要实现comparable接口,重写compareto();方法
(2)comparator:相当于找一个第三方裁判,比较两个
(3)comparator排序规则:o1 - o2 升序 , o2 - o1 降序
(4)comparator中有一个compare();方法,重写定义规则
//用comparator的排序
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("sad",22));
Collections.addAll(list,new Student("liuying",22),new Student("liu",11));
System.out.println(list);//[Student{name='sad', age=22}, Student{name='liuying', age=22}, Student{name='liu', age=11}]
Collections.sort(list, new Comparator<Student>() {
//重写排序规则
@Override
public int compare(Student o1, Student o2) {
//return o1.getAge() - o2.getAge();//升序
int result = o1.getAge() - o2.getAge();
if (result == 0){
result = o1.getName().charAt(0) - o2.getName().charAt(0);
}
return result;
}
});
System.out.println(list);//[Student{name='liu', age=11}, Student{name='liuying', age=22}, Student{name='sad', age=22}]
9.map接口
java.util.Map<K,V>集合
public interface Map<K,V>
1.map集合的特点
- map集合是一个双列集合,一个元素包含两个值(key和value)
- map集合中的元素,key和value的数据类型可以一样,也可以不一样
- map集合中的元素,key不允许重复,value可以重复
- map集合中的元素,key和value一一对应
2.map常用的子类hashmap集合
- java.util.HashMap<K,V>
- public class HashMap<K,V> implements Map<K,V>
- hashmap集合的特点:
(1)hashmap底层是哈希表:查询速度快
jdk1.8前:数组 + 单项链表
jdk1.8后:数组 + 红黑树(链表长度超过8):提高查询速度
(2)hashmap是一个无需的集合,存储和取出的顺序可能不一样
3.hashmap的子类linkedhashmap集合(有序)
- java.util.LinkedHashMap<K,V>
- public class LinkedHashMap<K,V>extends HashMap<K,V>implements Map<K,V>
- linkedhashmap集合的特点:
(1)linkedhashmap集合底层是一个哈希表 + 链表(保证元素的顺序)
(2)linkedhashmap集合是一个有序的集合,存储和取出的元素顺序一致
4.map接口的常用方法
- 常规方法
(1) V put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。
返回值V:
存储键值对的时候,key不重复,返回值V是null
存储键值对的时候,key重复,会使用新的value替换map集合中重复的value,返回被替换的value值
(2)V get(Object key) 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
(3) V remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
(4) boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。
2. map集合的遍历方式有两种:
(1) Set keySet() 返回此映射中包含的键的 Set 视图。 通过键找值的方法输出map集合的内容
(2) Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的 Set 视图。

3. 注意:
static interface Map.Entry<K,V> 映射项(键-值对)。
map集合中有嵌套静态类, entryset()方法遍历map集合,返回map.entry类型的对象集合
4. public static interface Map.Entry<K,V>
5. map.entry接口常用的方法
(1)K getKey() 返回与此项对应的键。
(2)V getValue() 返回与此项对应的值。
Map<String, Integer> map = new HashMap<>();
map.put("liuying",22);
map.put("ly",21);
map.put("liu",25);
map.put("liuying",20);
map.put("aaa",28);
System.out.println(map);//{aaa=28, liuying=20, liu=25, ly=21}
Integer liu = map.remove("liu");
System.out.println(liu);//25
System.out.println(map);//{aaa=28, liuying=20, ly=21}
Integer integer = map.get("liuying");
System.out.println(integer);//20
boolean b = map.containsKey("liuying");
System.out.println(b);//true
//使用keyset()方法遍历map集合
Set<String> set = map.keySet();
System.out.println(set);//[aaa, liuying, ly]
//使用迭代器遍历set集合
Iterator<String> iter = set.iterator();
while(iter.hasNext()){
String name = iter.next();
Integer age = map.get(name);
System.out.println(name + "==" + age);//aaa==28,liuying==20,ly==21
}
System.out.println("-----------");
//使用entryset遍历map
Set<Map.Entry<String, Integer>> entries = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
while (iterator.hasNext()){
Map.Entry<String, Integer> next = iterator.next();
String name = next.getKey();
Integer age = next.getValue();
System.out.println(name +"=" + age);//aaa=28 liuying=20 ly=21
}
5.hashmap存储自定义类型的键值
map集合必须保证key值是唯一的:
作为key的元素必须覆盖重写hashcode和equals方法,以保证key唯一
/*map集合存储自定义类型
* key:person类,person类就必须重写hashcode();方法和equals();方法
* value:string类
* 未重写hashcode和equals方法
* */
private static void demo2() {
HashMap<Person, String> map = new HashMap<>();
map.put(new Person("ly",20),"上海");
map.put(new Person("liu",28),"天津");
map.put(new Person("liuying",22),"无锡");
map.put(new Person("liuying",22),"北京");
System.out.println(map);//{Person{name='liuying', age=22}=无锡, Person{name='liuying', age=22}=北京, Person{name='liu', age=28}=天津, Person{name='ly', age=20}=上海}
Set<Map.Entry<Person, String>> set = map.entrySet();
for (Map.Entry<Person, String> entry : set) {
Person person = entry.getKey();
String address = entry.getValue();
System.out.println(person + "==" +address);//Person{name='liuying', age=22}==无锡Person{name='liuying', age=22}==北京Person{name='liu', age=28}==天津Person{name='ly', age=20}==上海
}
}
/*map集合存储自定义类型
* key:person类,person类就必须重写hashcode();方法和equals();方法
* value:string类
* 重写hashcode和equals方法后
* */
private static void demo3() {
HashMap<Person, String> map = new HashMap<>();
map.put(new Person("ly",20),"上海");
map.put(new Person("liu",28),"天津");
map.put(new Person("liuying",22),"无锡");
map.put(new Person("liuying",22),"北京");
System.out.println(map);//{Person{name='liu', age=28}=天津, Person{name='liuying', age=22}=北京, Person{name='ly', age=20}=上海}
Set<Map.Entry<Person, String>> set = map.entrySet();
for (Map.Entry<Person, String> entry : set) {
Person person = entry.getKey();
String address = entry.getValue();
System.out.println(person + "==" +address);//Person{name='liu', age=28}==天津Person{name='liuying', age=22}==北京Person{name='ly', age=20}==上海
}
}
/*map集合存储自定义类型元素
key:string类型
value:person类型*/
private static void demo1() {
HashMap<String, Person> map = new HashMap<>();
map.put("北京",new Person("liuying",23));
map.put("上海",new Person("ly",22));
map.put("天津",new Person("liu",20));
map.put("北京",new Person("lx",28));
Set<String> set = map.keySet();
for (String area : set) {
Person person = map.get(area);
System.out.println(area+ "--->"+person);//上海--->Person{name='ly', age=22}天津--->Person{name='liu', age=20}北京--->Person{name='lx', age=28}
}
}
6.linkedhashmap集合
- java.util.LinkedHashMap<K,V>
- public class LinkedHashMap<K,V>extends HashMap<K,V>implements Map<K,V>
- hashmap集合不能保证存取顺序,linkedhashmap集合保证存取顺序
7.另一个被取代的实现类hashtable集合
java.util.Hashtable<K,V>
public class Hashtable<K,V> implements Map<K,V>,
- hashtable集合底层也是一个哈希表,是一个线程安全的集合,单线程集合,速度慢
- hashmap集合底层是一个哈希表,是一个线程不安全的集合,多线程集合,速度快
- hashmap集合和之前所有的集合,都可以存储null键,null值
- hashtable集合不能存储null键,null值
- hashtable和vector一样,在jdk1.2之后,被更先进的集合(hashmap和arrayist)取代
- hashtable的子类properties依然活跃在历史舞台
- properties是唯一一个和io流相结合的集合
10.jdk9对集合添加的优化(of();方法)
1.jdk9新特性:
static List of(E… elements)
static Set of(E… elements)
static <K,V> Map<K,V> of()
- list接口,set接口,map接口,里面增加了一个静态方法of(),可以给集合一次性添加多个元素
- 使用前提:当集合中存储元素的个数已经确定,不再改变时
- 注意
(1)of();方法只适用于list接口,set接口,map接口,不适用于接口的实现类
(2)of方法的返回值是一个不能改变的集合,集合不能再使用add();put();方法添加元素,会抛出异常
(3)set接口和map接口在调用of();方法时,不能有重复的元素,会抛出异常
/* Map<String, String> map = new HashMap<>();不能用map的实现类调用of
map.of//编译报错*/
Map<String, Integer> map = Map.of("liuying", 22, "ly", 23, "liu", 20);
System.out.println(map);//{ly=23, liu=20, liuying=22}
//map.put("asd",22);//UnsupportedOperationException
List<Integer> list = List.of(1, 3, 2, 4, 3, 3);
System.out.println(list);//[1, 3, 2, 4, 3, 3]
//list.add(2);//UnsupportedOperationException
// Set<Integer> set = Set.of(1, 3, 4, 2, 5, 1, 2);//IllegalArgumentException
Set<Integer> set = Set.of(1, 3, 4, 2, 5);
System.out.println(set);//[1, 2, 3, 4, 5]
//set.add(1);//UnsupportedOperationException
本文深入讲解Java集合框架,包括Collection、List、Set、Map接口及其主要实现类的特性与使用方法,探讨泛型、迭代器、哈希表等关键概念,解析ArrayList、LinkedList、HashSet、HashMap的工作原理及优化技巧。
、泛型、数据结构、list接口、set接口、可变参数、collections工具类、Map接口、of方法优化&spm=1001.2101.3001.5002&articleId=105073195&d=1&t=3&u=b010b6af7a1140e1a627733dbe53e14d)
440

被折叠的 条评论
为什么被折叠?



