集合
Collection接口
概述
数组和集合都是Java中提供的容器
集合: 英文译为 Collection,用来存放对象的容器,集合中可以存放不同类型的对象,并且集合的长度可变。
在编程时,常常需要集中存放多个数据,可以使用数组来保存多个对象,但数组长度不可变化,一旦在初始化数组时指定了数组长度,这个数组长度就是不可变的,如果需要保存数量变化的数据,数组就有点无能为力了;
为了保存数量不确定的数据,以及保存具有映射关系的数据,Java提供了集合类。集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。
小结: 集合和数组的对比:
1)数组中的元素可以基本类型的值,也可以是对象; 而集合中只能保存对象
2)数组一旦指定了长度,长度就不能再改变; 而集合的长度是可以随时改变的
3)往数组中插入元素非常麻烦,需要将插入位置后面的元素往后移动; 或者删除数组中间位置的某一个元素, 需要将删除位置后的元素往前移动; 而如果往集合中插入元素或者删除集合中的某一个元素,直接使用现成的方法操作即可
集合的继承结构
由于需求不同,Java就提供了不同的集合类。这多个集合类的数据结构不同,但是它们都是要提供存储和遍历功能的,我们把它们的共性不断的向上提取,最终就形成了集合的继承体系结构图。
Collection接口
|-- List接口
|-- ArrayList类
|-- LinkedList类
|-- Set接口
|-- HashSet类
|-- TreeSet类
解释说明:
- Collection集合是所有单值集合的顶层接口, 其中定义了常用的用于操作集合以及集合中元素的方法
例如: 添加元素、删除元素、获取元素、获取集合长度、判断功能、将集合转成数组、迭代器遍历元素等功能
- List是Collection的子接口,特点是其中的元素是有序的(即:元素存入集合时的顺序和取出的顺序一致)
可以通过下标访问List中的元素,另,List集合中的元素是可以重复的(包括null)
- Set也是Collection的子接口,特点是其中的元素是无序(即:元素存入集合时的顺序和取出的顺序不一定一致)
无法通过下标访问Set中的元素,另外,Set集合中的元素是不可以重复的
学习集合的建议:
- 学习接口中提供的共性方法
- 通过实现类创建对象, 调用这些共性方法
常用方法
!!boolean add(E e)
– 往集合中添加指定元素e
boolean addAll(Collection c)
– 将小集合添加到大集合中
!!boolean isEmpty()
– 如果集合中没有任何元素(空集合), 返回true
boolean contains(Object o)
– 如果此集合中包含指定元素o, 则返回true
boolean containsAll(Collection c)
– 如果此集合中包含指定 集合c 中的所有元素,则返回 true。
– 例如c1中有 “a”,“b”,“c”,“d”, 而c2中有"a",“b”, 则c1包含c2, 返回true
若,c1中有 “a”,“b”,“c”,“d”, 而c2中有"x",“a”,“b”, 则c1不包含c2, 返回false
!!int size()
– 返回集合的大小(元素个数)
!!boolean remove(Object o)
– 从集合中删除指定的元素o, 删除成功则返回true
– 如果删除的元素不存在导致删除失败, 则返回false
– 如果元素o在集合中出现多次,仅删除第一个
boolean removeAll(Collection c)
– 删除此集合中那些也包含在指定集合c中的所有元素, 若有共同元素, 则删除并返回true
例如 c1中有 “a”,“b”,“c”,“d”, 而c2中有"x",“a”,“b”,
c1.removeAll(c2),只删除c1中两个共同的元素 “a”,“b”, 对c2没有影响
– 如果两个集合中没有共同元素, 则不删除, 返回false
boolean retainAll(Collection c)
– 仅保留此集合中那些也包含在指定集合c中的元素
例如 c1中有 “a”,“b”,“c”,“d”, 而c2中有"x",“a”,“b”,
c1.retainAll(c2),只保留c1中两个共同的元素 “a”,“b”, 对c2没有影响
void clear()
– 删除此集合中的所有元素
Object[] toArray()
– 将此集合转成对象数组
boolean equals(Object o)
– 比较此 collection 与指定对象是否相等。
!!Iterator iterator()
– 返回此集合中所有元素组成的迭代器。
实例1:CollectionDemo1
package Part06Collection;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
/**
* JAVA集合框架
* 集合和数组一样的,都是用来存储一组元素,但是集合将元素的操作都封装成了方法,操作简单
* 并且集合还提供了多种不同的实现供我们使用
* java.util.Collection是所有集合的顶级接口,里面定义了所有的集合的必须具备的功能
* 集合相比数组的优点:1.不需要指定长度,存储的内容随意个2.存储的类型可以任意
* 集合中常用的两个子类:
* java.util.List:可重复的集合,且有序.通常被称之为'线性表'
* java.util.Set:不可重复的集合
* 上述两个都是接口
*/
public class CollectionDemo1 {
public static void main(String[] args) {
//集合中只能存放引用类型
Collection c = new ArrayList();
/*
* add:加
* boolean add(E e) 这个E是泛型,这里就先理解为时Object
* 向当前集合中添加一个元素,如果元素添加成功,会返回一个true,否则返回false
*/
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
c.add(123);//c.add(Integer.valueOf(123)) 会触发自动装箱特性
System.out.println(c);//[one, two, three, four, five]
/*
* int size()
* 返回当前集合的元素个数
* 区别于数组的length,数组的length表示数组能存多少,但是存不够,长度也这么长
* 但是size不是,size表示集合中有几个元素个数
* 那这个方法返回的是int,所以集合返回的int的最大值,就是集合中能存储的最大个数嘛?
* 集合中可以存储更多的元素
* size: 尺寸,大小
*/
int size = c.size();
System.out.println("集合的元素个数:"+size);
/*
* empty: 空的
* boolean isEmpty()
* 判断当前集合是否为空集合,当size为0时,返回true
*/
boolean isEmpty = c.isEmpty();
System.out.println("集合是否为空:"+isEmpty);
//清空集合 把集合变为空集合
c.clear();
System.out.println(c);
System.out.println("集合的元素个数:"+c.size());
System.out.println("集合是否为空:"+c.isEmpty());
}
}
实例2:CollectionDemo2
package Part06Collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
public class CollectionDemo2 {
public static void main(String[] args) {
Collection c = new ArrayList();
//Collection c = new HashSet();//不可以重复存储相同的元素
c.add(new Point(1, 2));
c.add(new Point(3, 4));
c.add(new Point(5, 6));
c.add(new Point(7, 8));
c.add(new Point(9, 0));
c.add(new Point(1, 2));
/*
* 集合中重写了toString(),格式为:
* [元素1.toString(),元素2.toString(),元素3.toString(),...]
* 所以如果输出的集合中的元素对象需要指定格式,需要对应类重写toString方法
*/
System.out.println(c);
Point p = new Point(1, 2);
/*
* boolean contains(Object o)
* 判断当前集合是否包含给定元素
* 元素是否包含取决于当前给定元素与集合中的元素的equals方法比较后,
* 是否结果为true
* 默认equas是比较内存地址的,如果需要按照指定的元素的值比较,
* 可以重写该类的equals方法
*/
boolean contains = c.contains(p);
System.out.println("当前集合是否包含该元素:"+contains);
/*
* remove方法删除元素
* 删除时,也是会和集合中的元素使用equals比较,如果是true可以删除
* 对于List而言,可以存储重复的元素,对这种情况,仅会删除一次
*/
c.remove(p);
System.out.println(c);
}
}
Point
package Part06Collection;
import java.util.Objects;
public class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public String toString() {
return "Point{" +
"x=" + x +
", y=" + y +
'}';
}
//alt+insert 选择equals and hashCode,然后一路回车即可
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
return x == point.x && y == point.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
实例3:CollectionDemo3
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZXhVxuU-1654135210710)(pic/image-20220521094249618.png)]
package Part06Collection;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo3 {
public static void main(String[] args) {
Collection c = new ArrayList();
Point p = new Point(1, 2);
c.add(p);//将p元素添加到集合中
System.out.println("p:"+p);
System.out.println("c:"+c);
p.setX(2);//将p对象的x属性修改为2
System.out.println("p:"+p);
System.out.println("c:"+c);
}
}
实例4:CollectionDemo4
package Part06Collection;
import java.util.ArrayList;
import java.util.Collection;
/**
* 集合间的操作
*/
public class CollectionDemo4 {
public static void main(String[] args) {
Collection c1 = new ArrayList();
c1.add("java");
c1.add("c++");
c1.add(".net");
System.out.println("c1:"+c1);
Collection c2 = new ArrayList();
c2.add("android");
c2.add("ios");
c2.add("java");
System.out.println("c2:"+c2);
/*
* boolean addAll(Collection c)
* 将给定的集合中的所有元素添加到当前的集合中(取并集)
* 操作后,当前集合发生了变化则返回true
*/
boolean b = c1.addAll(c2);
System.out.println(b);
System.out.println("c1:"+c1);
System.out.println("c2:"+c2);
Collection c3 = new ArrayList();
c3.add("c++");
c3.add("java");
//c3.add("php"); //不加php,就返回true,加了php,就返回false
/*
* boolean containsAll(Collection c)
* 判断当前集合中是否包含给定集合中的所有元素
*/
boolean b1 = c1.containsAll(c3);
System.out.println("包含所有:"+b1);
/*
* 取交集 将两个集合中都有的元素进行保留
*/
c1.retainAll(c3);
System.out.println("c1:"+c1);
System.out.println("c3:"+c3);
/*
* 删除交集. 将c1与c3的共有元素删除(c3不受影响)
*/
c1.removeAll(c3);
System.out.println("c1:"+c1);
System.out.println("c3:"+c3);
}
}
集合的遍历
IteratorDemo
package Part06Collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* 集合的遍历
* Collection层面不支持随机访问操作(根据指定的位置获取对应的元素)
* 但是集合支持遍历操作,我们可以通过遍历集合的方式拿到集合中的每一个元素
* die
* 集合提供了统一的遍历方式:迭代器遍历
* 对应方法:
* Iterator iterator()
* 该方法会返回一个用于遍历当前集合的迭代器
* java.util.Iterator是迭代器的接口,定义了迭代器遍历集合的基本操作,
* 所有的集合都提供了一个变量自身元素的迭代器实现类,我们无需记住他们的名字,
* 统一将他们都看做是Iterator即可.迭代器遍历集合遵循的步骤:问->取->删.
* 其中删除不是必须的步骤
*/
public class IteratorDemo {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("one");
c.add("#");
c.add("two");
c.add("#");
c.add("three");
c.add("#");
c.add("four");
c.add("#");
c.add("five");
System.out.println(c);
//获取迭代器对象
Iterator it = c.iterator();
/*
* boolean hasNext()
* 判断集合是否还有"下一个"元素可以遍历,迭代器的起始位置可以理解为是
* 集合第一个元素的前一个,因此第一次调用hasNext方法就是来判断是否有第一个元素
* E next()
* 获取集合的"下一个元素",获取后迭代器的位置向后移动一个位置
*/
while (it.hasNext()){
String e = (String) it.next();
System.out.println(e);
if("#".equals(e)){
/*
* 迭代器在遍历的过程中,不能通过集合的方法来增删元素,否则迭代器
* 会抛出并发修改异常
*/
//c.remove(e);
/*
* 迭代器提供了remove方法可以将本次next获取的元素从集合中删除
*/
it.remove();
}
}
System.out.println(c);
}
}
增强型for循环
NewForDemo
package Part06Collection;
import java.util.ArrayList;
import java.util.Collection;
/**
* JDK5推出时,推出了一个新特性:增强型for循环
* 通常也称之为叫做新循环
* 新循环不能取代传统for循环的工作,它的出现仅仅只是为了使用相同的语法遍历集合或者数组
* 语法:
* for(元素类型 e : 集合或者数组){
*
* }
*/
public class NewForDemo {
public static void main(String[] args) {
String[] array = {"one","two","three","four","five"};
//传统for循环遍历数组
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
//新循环遍历数组 array.for
for (String s : array){
System.out.println(s);
}
Collection<String> c = new ArrayList();
c.add("一");
c.add("二");
c.add("三");
c.add("四");
c.add("五");
for (Object o : c){
String str = (String)o;
System.out.println(str);
}
//新循环底层遍历就是迭代器遍历,编译器会将其改回迭代器遍历,
//所以我们如果想删除集合中的元素时,这种新循环就不适合了
for (String s : c) {
System.out.println(s);
}
}
}
List集合
概述
List是一个有序的Collection(List是Collection的子接口),使用此接口能够精确的控制每个元素插入的位置,能够通过索引(类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。
List 接口存储一组可重复、有序(插入顺序)的对象。
特点
-
元素有下标,可以通过下标访问元素
-
元素是有序的(存入集合的顺序和取出的顺序一定相同)
-
元素可以重复(包括null)
List方法测试
ListDemo
package Part06Collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* java.util.List接口
* List继承自Collection,是最常用的一类集合,特点:可以存放重复元素且有序
* List里提供了一套可以通过下标操作元素的方法.
* 常用的实现类:
* java.util.ArrayList: 内部使用的数组实现,查询性能好
* java.util.LinkedList: 内部使用的链表实现,增删性能好,收尾增删性能最佳
* 对性能没有苛刻要求下,通常还是使用ArrayList即可
*/
public class ListDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
System.out.println(list);
//获取集合中的第三个元素
/*
* E get(int index)
* 获取指定的下标处对应的元素
* 下标起始值是0
*/
String str = list.get(2);//与数组获取元素的功能一致 String str = arr[2]
System.out.println(str);
//由于list集合有下标,所以可以使用for循环遍历
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
/*
* E set(int index,E e)
* 将给定元素设置到指定位置上,返回值是该位置原来的元素
* 替换元素的操作
*/
//[one, six, three, four, five]
String old = list.set(1, "six");//将第二个位置原来的two替换为six,并将two返回
System.out.println(old);
System.out.println(list);
//在不创建新的集合的前提下,将集合元素翻转
/*
* one, six, three, four, five
* five,four,three, six , one
* 0 1 2 3 4
* 当0换到4
* 当1换到3
*/
for (int i=0;i<list.size()/2;i++){//i:0 1
//获取正数位置上的元素
String e = list.get(i);//one
//将获取到的正数位置的元素替换到倒数位置上
e = list.set(list.size()-1-i, e);
//将原倒数位置上的元素替换到正数位置上
list.set(i, e);
}
System.out.println(list);
Collections.reverse(list);//翻转集合
System.out.println(list);
}
}
ListDemo2
package Part06Collection;
import java.util.ArrayList;
import java.util.List;
/*
* List重载了一对add,remove方法
*/
public class ListDemo2 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("一");
list.add("二");
list.add("三");
list.add("四");
list.add("五");
System.out.println(list);
/*
* void add(int index,E e)
* 给指定元素插入到指定位置
* 区别于set方法,set方法是覆盖
*/
list.add(3,"老六儿");
System.out.println(list);
/*
* E remove(int index)
* 删除并返回指定位置上的元素
*/
String old = list.remove(2);
System.out.println(old);
System.out.println(list);
}
}
ListDemo3
package Part06Collection;
import java.util.ArrayList;
import java.util.List;
/**
* List集合提供的方法:
* List subList(int start,int end)
* 获取当前集合的制定范围内的子集
*/
public class ListDemo3 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
//向集合中添加0-9的元素
for (int i=0;i<10;i++){
list.add(i);
}
System.out.println(list);
//获取子集[3-7] 含头不含尾
List<Integer> sub = list.subList(3, 8);
System.out.println(sub);
//将子集中的每个元素都扩大10倍
for (int i = 0; i < sub.size(); i++) {
sub.set(i, sub.get(i)*10);
}
System.out.println(sub);
//对子集的操作就是对原集合对应元素的操作
System.out.println(list);
//清除集合中1-8这部分元素
list.subList(1, 9).clear();
System.out.println(list);
}
}
集合和数组的转换
集合转换数组:CollectionToArrayDemo
package Part06Collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
/**
* 集合转换为数组
* Collection中定义一个方法toArray,可以将一个集合转换为一个数组
*/
public class CollectionToArrayDemo {
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
c.add("老大");
c.add("二娃");
c.add("三弟");
c.add("四兄");
c.add("五妹");
System.out.println("集合:"+c);
//Object[] array = c.toArray();
//需要传入一个指定长度的对应类型的数组
String[] array = c.toArray(new String[c.size()]);
System.out.println("数组:"+ Arrays.toString(array));
}
}
数组转换集合: ArrayToListDemo
package Part06Collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 数组转换为List集合
* 数组的工具类Arrays提供了一个静态的方法asList,可以将一个数组转换为
* 一个List集合
*/
public class ArrayToListDemo {
public static void main(String[] args) {
String[] array = {"one","two","three","four","five"};
System.out.println("数组:"+ Arrays.toString(array));
List<String> list = Arrays.asList(array);
System.out.println("集合:"+list);
//对该集合的操作就是对原数组对应的操作,也就是改了集合数组也会跟着改
list.set(1, "six");//将下标1的元素覆盖为six
System.out.println("集合:"+list);
System.out.println("数组:"+ Arrays.toString(array));
/*
* 由于数组是定长的,并且操作集合就会改动数组,所以当我们对集合进行增删时,
* 就会导致对数组也进行同等操作,这时就会抛出异常
* UnSupportedOperationException
* UnSupported 不支持的
* Operation 操作
*/
//list.add("seven");
System.out.println("集合:"+list);
System.out.println("数组:"+ Arrays.toString(array));
/*
* 如果有增删的需求,就需要另外的创建一个集合,并先将数组转换的集合的内容导入到新集合中即可
*/
//List<String> list2 = new ArrayList<>();
//list2.addAll(list);
/*
* 所有的集合都支持一个参数为Collection的构造器,
* 目标是在创建当前集合的同时,将参数集合的所有元素也包含进去
*/
List<String> list2 = new ArrayList<>(list);
list2.add("seven");
System.out.println(list2);
}
}
集合的排序
SortListDemo
package Part06Collection;
import java.util.*;
/**
* 集合的排序
* 集合的工具类java.util.Collections提供了一个静态方法sort,
* 可以对List集合进行自然排序
*/
public class SortListDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 10; i++) {
//每次向集合中添加一个100以内的随机整数
list.add(random.nextInt(100));
}
System.out.println(list);
Collections.sort(list);//自然排序,从小到大
System.out.println(list);
}
}
SortListDemo2
package Part06Collection;
import java.util.*;
/**
* 排序自定义类型元素
*/
public class SortListDemo2 {
public static void main(String[] args) {
List<Point> list = new ArrayList<>();
list.add(new Point(1, 2));
list.add(new Point(15, 66));
list.add(new Point(3, 4));
list.add(new Point(9, 0));
list.add(new Point(7, 8));
System.out.println(list);
/*
* sort方法对排序的集合有要求:要求集合元素必须实现了Comparable接口.
* 实现了该接口的类,并且重写一个方法compareTo方法用于定义比较大小的规则,
* 从而进行元素间的比较,进行排序否则编译就不通过
*/
//Collections.sort(list);
//使用匿名内部类的形式创建一个比较器,可以使用泛型约束我们比较的是两个Point
Comparator<Point> com = new Comparator<Point>() {
/*
* 实现比较器之后,必须要重写方法compare,
* 该方法用来定义参数o1和参数o2的比较大小规则,
* 返回值用来表示o1和o2的大小关系
*/
@Override
public int compare(Point o1, Point o2) {
//点与点比较一般都是距离原点的距离越远,就越大
int len1 = o1.getX()*o1.getX() + o1.getY()*o1.getY();
int len2 = o2.getX()*o2.getX() + o2.getY()*o2.getY();
return len1-len2;
}
};
Collections.sort(list,com);
System.out.println(list);
}
}
Map接口
概述
Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的键(key)另外一组值用于保存Map里的值(value),键和值是一一对应的关系,称为映射。根据键就能找到对应的值,类似于生活中一张身份证对应一个人一样。
Map的key和value可以是任何引用类型的数据,其中key不允许重复,同一个Map对象的任何两个key通过equals方法比较总是返回false。
特点
\1) Map集合中每个元素都有两个值, 分别是key(键) 和 value(值)
\2) Map集合中的key(键)不允许重复, 在第二次添加已有的key时, value会被会覆盖
\3) Map集合中的元素是无序的(即元素存入集合的顺序和取出时的顺序很可能不一致)
\4) Map集合中的key和value具有映射关系, 可以通过key(键)来获取对应的value(值)
key和value之间存在单向一对一关系,即通过指定的key,总能找到唯一的、确定的value。从Map中取出数据时,只要给出指定的key,就可以取出对应的value。
如果把Map里的所有key放在一起来看,它们就组成了一个Set集合(所有的key没有顺序,key与key之间不能重复),实际上Map确实包含了一个keySet()方法,用于返回Map里所有key组成的Set集合。
如果把Map里的所有value放在一起来看,它们又非常类似于一个List:元素与元素之间可以重复,每个元素可以根据索引来查找,只是Map中的索引(也就是key)不是从0开始的整数值,而是任意类型的对象;
如果需要从List集合中取出元素,则需要提供该元素的数字索引;如果需要从Map中取出元素,则需要提供该元素的key。因此,Map有时也被称为字典,或关联数组。
继承结构
Map接口
|— HashMap类
|— TreeMap类
|— Hashtable类
解释说明:
- Map集合是采用键-值对(key-value)的存储方式, 键(key)、值(value)可以是引用类型的数据, key不允许重复, vaue可以重复, key和value是一对一的关系, 通过指定的key总能找到唯一的、确定的value值
- HashMap 和 Hashtable 都是Map接口的实现类,它们之间的关系完全类似于ArrayList和Vector的关系
\1) HashMap是线程不安全的, 所以HashMap的性能要比HashTable高一些
\2) HashMap可以使用null作为key或value, Hashtable不允许使用null作为key和value;
\3) Hashtable是一个古老的Map实现类,JDK 1.0出现,出现时,Java还没有提供Map接口,命名没有遵守Java的命名规范,与Vector类似的是,尽量少用Hashtable实现类,即使需要创建线程安全的Map实现类,也无须使用Hashtable实现类,可以通过别的方式来解决线程安全问题。
- TreeMap是Map的子接口SortedMap的的实现类, 是可以支持对内部元素进行排序的类, 也正因为如此, TreeMap的执行效率通常要比HashMap和HashTable慢。
MapDemo
package Part06Collection;
import java.util.HashMap;
import java.util.Map;
/**
* java.util.Map接口 查找表
* Map体现的结构就是一个多行两列的表格,其中左列称为"key",右列称为"value"
* Map总是以key-value的形式保存一组数组.并且可以根据key获取对应的value
* Map有一个要求,key不允许重复(equals比较)
*
* 常用Map的实现类:
* java.util.HashMap,我们称之为"散列表",当今查询速度最快的数据结构
*/
public class MapDemo {
public static void main(String[] args) {
//Map声明时,可以指定泛型,不过需要指定两个类型,一个是key的类型,一个value的类型
Map<String,Integer> map = new HashMap();
/*
* V put(K k,V v);
* 向当前map中存储一组键值对
*/
map.put("语文", 80);
//map.put("数学", 70).intValue();
/*
* 如果Map的value是包装类型,获取时,不要使用基本类型接收,
* 避免自动拆箱时,引发空指针
*/
Integer value = map.put("数学", 70);
System.out.println("value:"+value);//如果key不存在,就返回null
map.put("英文", 34);
map.put("化学", 60);
//{英文=34, 数学=70, 化学=60, 语文=80}
System.out.println(map);
//map在put时,如果key不存在,就直接存储,如果key存在,就会覆盖
value = map.put("数学", 150);
System.out.println("value:"+value);//如果key存在,返回被替换掉的元素
System.out.println(map);
/*
* V get(Object k)
* 根据给定的key获取对应的value,如果给定的key不存在,返回为null
*/
Integer score = map.get("语文");
System.out.println("语文成绩:"+score);
score = map.get("体育");
System.out.println("体育成绩:"+score);
//返回map中的元素个数
int size = map.size();
System.out.println("集合中有"+size+"个元素");
/*
* 删除给定的key对应的这组键值对,返回值为这个key对应的value
*/
score = map.remove("数学");
System.out.println("删除了数学成绩:"+score);
size = map.size();
System.out.println("集合中有"+size+"个元素");
//可以分别判断Map中是否包含给定的key或者value
boolean ck = map.containsKey("英文");
System.out.println("是否包含key:"+ck);
boolean cv = map.containsValue(100);
System.out.println("是否包含value:"+cv);
}
}
MapDemo2
package Part06Collection;
import java.util.*;
/**
* Map的遍历
* Map支持三种遍历方式:
* 1:单独遍历key
* 2:遍历每一组键值对
* 3:单独遍历value(这个操作不常用)
*/
public class MapDemo2 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("语文", 98);
map.put("数学", 100);
map.put("英语", 80);
map.put("物理", 60);
map.put("java", 150);
System.out.println(map);
/*
* Set keySet()
* 将当前的map中所有的key以一个Set集合的形式返回
*/
Set<String> keySet = map.keySet();
for (String s : keySet) {
System.out.println("map的key是:"+s);
System.out.println("map的value是:"+map.get(s));
}
/*
* Collection values()
* 将所有的value以一个集合的形式返回
*/
Collection<Integer> values = map.values();
for (Integer value : values) {
System.out.println("map的value是:"+value);
}
/*
* 遍历每一组键值对
* Set entrySet()
* 将当前Map中的每一组键值对以Entry对象实例形式来表示,存入集合中并返回,
*/
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
for (Map.Entry<String, Integer> entry : entrySet) {
//从entry对象中获取key值
String key = entry.getKey();
//从entry对象中获取value值
Integer value = entry.getValue();
System.out.println("key:"+key+"===="+"value:"+value);
}
/*
* JDK1.8之后,集合和Map都支持了基于lambda表达式形式的遍历
*/
map.forEach(
//此处k和v起什么名字无所谓,第一个值是key,第二个值是value
(k,v)-> System.out.println(k+":"+v)
);
Collection<String> c = new ArrayList<>();
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
c.forEach(
(e)-> System.out.println(e)
);
//如果参数只有一个,小括号可以省略
c.forEach(
e-> System.out.println(e)
);
//如果输出的参数和传入的参数都是一个,参数也可以省略,并且替换为::
c.forEach(
System.out::println
);
}
}
代码分析
Demo1
package Part06Collection;
import java.util.ArrayList;
import java.util.Collection;
/**
* 局部变量存在栈中
* 对象在堆里
* 属性在对象中(在堆里)
*
* 基本类型保存的值就是值本身
* 引用类型保存的值是对象在堆中的地址
*/
public class Demo {
public static void main(String[] args) {
String s = "hello";
int a = 1;
Point p = new Point(1, 2);
Collection c = new ArrayList();
c.add(p);
test(s, a, p, c);
System.out.println("s:"+s);
System.out.println("a:"+a);
System.out.println("p:"+p);
System.out.println("c:"+c);
}
public static void test(String s,int a,Point p,Collection c){
a++;
s= s + "world";
p.setX(3);
p = new Point(4, 5);
c.clear();
c.add(p);
c = new ArrayList();
p.setX(7);
c.add(p);
}
}
- 执行test方法最后一行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Erqsksa-1654135210713)(pic/image-20220523202224814.png)]
- 执行完test方法,清空test方法的局部变量和引用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EdrAJqlP-1654135210714)(pic/image-20220523202200438.png)]
- 清理堆中无引用对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BXCcDpZd-1654135210715)(pic/image-20220523202126267.png)]
Demo2
package Part06Collection;
import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
/**
* 局部变量存在栈中
* 对象在堆里
* 属性在对象中(在堆里)
*
* 基本类型保存的值就是值本身
* 引用类型保存的值是对象在堆中的地址
*/
public class Demo2 {
public static void main(String[] args) {
int a = 1;
String str = "hello";
Point p = new Point(1,2);
String[] arr = {"one","two","three",str};
int[] arr1 = {1,2,3,4,a};
Point[] arr2 = {new Point(1,2),new Point(3,4),new Point(5,6),p};
dosome(a,str,p,arr,arr1,arr2);
System.out.println("a:"+a);
System.out.println("str:"+str);
System.out.println("p:"+p);
System.out.println("arr:"+ Arrays.toString(arr));
System.out.println("arr1:"+Arrays.toString(arr1));
System.out.println("arr2:"+Arrays.toString(arr2));
}
public static void dosome(int a,String str,Point p,String[] arr,int[] arr1,Point[] arr2) {
arr1[a] = 3;
arr[a] = "str";
arr[a+1] = str;
str = "world";
str = arr[2];
str+="!!";
p.setX(4);
p = arr2[2];
p.setX(6);
arr2 = Arrays.copyOf(arr2, arr2.length-1);
arr2[2].setX(8);
arr2 = new Point[]{new Point(2,2),p};
arr2[arr2.length-1].setX(12);
}
}
- 执行dosome方法之前
- 执行dosome方法进行传参时
- dosome方法执行完毕
- dosome方法执行后,弹出相关局部变量,清除多余引用以及无引用对象