文章目录
集合
- 集合像一个容器,可以一次性容纳其他类型的多个数据,集合在JDK当中java.util包下。
- 在实际开发中,假设连接数据库,查询出数据库中10条记录,在java程序中会将10条数据封装成10个java对象,然后将10个java对象放到一个集合中,将集合传输当前端。之后遍历集合,读取数据。 (拉货的货车)
- 集合不能直接存储基本数据类型,另外集合也不能直接存储java对象,集合当中存储的都是java对象的内存地址(存储的引用),因为集合是一个对象,对象内部存储的是其他类型数据的内存地址。
- 在java中每一个不同的集合,底层会对应不同的数据结构,往不同的集合中存储元素,等于将数据放到了不同的数据结构当中,
- 数据结构:数据的存储结构,不同数据结构,数据的存储方式不同
- 数组、二叉树、链表、哈希表
- new ArrayList(); //创建一个集合,底层是数组——将检索发挥到极致
- new LinkedList(); //创建一个集合,底层是链表——将随机增删发挥到极致
- java中集合分类
- 单个方式存储元素:这一类集合的父接口:java.util.Collection;
- 以键值对存储元素:这一类集合的父接口:java.util.Map ;
Collection接口
- ArrayList集合底层采用的数据结构是数组。ArrayList是非线程安全。
- LinkedList集合底层采用的数据结构是双向链表数据结构
- Vetor集合底层采用的数据结构是数组。但是Vector是线程安全的,Vector所有的方法都有synchronized修饰,但是效率较低,所以Vector使用较少了。
- HashSet底层是HashMap,放到HashSet集合中的元素等同于放到HashMap集合key部分
- TreeSet底层是TreeMap,放到TreeSet集合中的元素等同于放到TreeMap集合的key部分
- List集合存储元素的特点:有序可重复——见例一
- 有序:存进去的顺序和取出的顺序相同
- 可重复:存进去1,可以再存储1
- Set集合存储元素的特点:无序不可重复——见例一
- 无序:存进去的顺序和取出的顺序不一定相同,Set集合没有下标
- 不可重复:存进去1,不能再次存储1
- SortedSet集合存储元素的特点:由于继承Set集合,所以他的特点是无序不可重复。但是放在SortedSet集合中的元素可以自动排序,称为可排序集合,放到该集合的元素是自动按照大小顺序排序的。
- 可排序:可以按照大小顺序排序。
Map
- Map集合和Collection没有关系
- Map集合以key和value键值对的方式存储元素
- key和value都存储java对象的内存地址。
- 所有Map集合的key特点:无序不可重复。遍历Map时,重点是获得key。
- SortedMap集合的key存储元素的特点:无序不可重复,放入SortedMap集合key部分的元素会自动按照大小顺序排序,称为可排序集合。
- TreeMp是一个二叉树结构
- Properties是线程安全的,因为继承HashTable,存储元素采用key和value形式,且只能支持String类型,不支持其他类型。properties被称为属性类。
Collection常用方法
- Collection存放元素类型
-
(货车里面什么都装)。【集合不能直接存储基本数据类型,也不能存储java对象,只是存储了java对象的内存地址 Collection c =new ArrayList();】未使用泛型之前,集合可以存放Object所有子类型 - 使用泛型之后,Collection只能存储某个具体的类型
-
- Collection常用方法:
- boolean add(E e) //添加
- int size() // 返回此 collection 中的元素数。
- void clear() //清空此 collection 中的所有元素(可选操作)。
- boolean contains(Object o) //如果此 collection 包含指定的元素o,则返回 true。
- boolean remove(Object o) //从 collection 中移除指定元素的单个实例
- boolean isEmpty() //判断集合中元素的个数是否为“0”
- Object[] toArray() //集合转数组
package Advance.gather;
import java.util.*;
/**
* @author 衣鱼
* Collection常用方法
* boolean add(E e)
* int size() // 返回此 collection 中的元素数。
* void clear() //清空此 collection 中的所有元素(可选操作)。
* boolean contains(Object o) //如果此 collection 包含指定的元素o,则返回 true。
* boolean remove(Object o) //从 collection 中移除指定元素的单个实例
* boolean isEmpty() //判断集合中元素的个数是否为“0”
* Object[] toArray() //集合转数组
*/
public class CollectionTest01 {
public static void main(String[] args) {
//创建一个Collection对象 ——错误
//Collection是一个接口,接口是抽象的,无法实例化
//Collection c = new Collection();
Collection c = new ArrayList(); //多态 父类型引用指向子类型对象
c.add(1200); //自动装箱 实际上放的是内存地址 Integer x =new Integer(1200);
c.add(new Object()); //放的内存地址
c.add(true);
//获取集合中元素的个数
System.out.println("集合中元素的个数"+c.size()); //3
//清空元素
c.clear();
System.out.println("集合中元素的个数"+c.size()); //0
//添加元素
c.add("hello");
c.add("world");
c.add(1);
//判断集合中是否包含1200
System.out.println(c.contains("1200")); //false
System.out.println(c.contains("hello")); //true
System.out.println(c.contains("hello world")); //false
//删除元素
c.remove(1);
System.out.println("集合中元素的个数"+c.size()); //2
//判断集合是否为空
/*@return <tt>true</tt> if this collection contains no elements
boolean isEmpty();
*/
System.out.println(c.isEmpty()); //false
c.clear();
System.out.println(c.isEmpty()); //true
c.add("hello");
c.add("world");
c.add(1);
//集合转换为数组 Object[] toArray()
Object[] objs=c.toArray();
for(int i =0;i<objs.length;i++) {
System.out.print(objs[i]+"\t"); //hello world 1
}
}
}
迭代/遍历理解
- 当集合的结构发生改变之后,迭代器必须重新获取,否则会产生错误【ConcurrentModificationException】———见迭代 remove
- Iterator中的方法
- boolean hasNext() //如果仍有元素可以迭代,则返回 true。
- Object next() //返回迭代的下一个元素。
- void remove() // 从迭代器指向的 collection 中移除迭代器返回的最后一个元素
package Advance.gather;
import java.util.*;
/**
* @author 衣鱼 ******
* 关于集合遍历/迭代 ——该实验的迭代方式是所以Collection通用的方式
* 在Map集合中不能用,在所有Collection子类中使用
* Iterator中的方法
* boolean hasNext() //如果仍有元素可以迭代,则返回 true。
* Object next() //返回迭代的下一个元素。
* void remove() // 从迭代器指向的 collection 中移除迭代器返回的最后一个元素
*/
public class CollectionTest02 {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
//添加元素
c.add("abc");
c.add("def");
c.add(100);
c.add(new Object());
//对集合进行遍历
//①获取集合对象的迭代器对象Iterator
Iterator it =c.iterator(); //拿到迭代器,利用迭代器的方法遍历集合
//②利用迭代器对象开始迭代
//boolean hasNext = it.hasNext();
while(it.hasNext()){ //如果hasNext为true执行
Object obj = it.next();
System.out.println(obj);
}
}
}
ArrayList;HashSet 的有序性、重复性理解
package Advance.gather;
import java.util.*;
/**
* @author 衣鱼
* ArrayList:有序 、可重复
* HashSet:无序、不可重复
*/
public class CollectionTest03 {
public static void main(String[] args) {
Collection c1 =new ArrayList(); //ArrayList:有序 、可重复
c1.add(1);
c1.add(2);
c1.add(3);
c1.add(4);
c1.add(1);
//创建Iterator对象
Iterator it =c1.iterator();
while(it.hasNext()) {
System.out.print(it.next()+"\t"); //1 2 3 4 1
}
System.out.println();
Collection c2 =new HashSet(); //HashSet:无序、不可重复
c2.add(1);
c2.add(4);
c2.add(2);
c2.add(8);
c2.add(4);
Iterator tt =c2.iterator();
while(tt.hasNext()) {
System.out.print(tt.next()+"\t"); //1 2 4 8
}
}
}
迭代—remove
- 在迭代集合元素的过程中,不能调用集合对象的remove方法,删除元素。
- 迭代器相当于对当前集合的状态拍了一个快照,迭代器迭代的时候,会参照这个快照进行迭代,一旦快照和真实的集合状态不匹配【remove】,就会出现问题。而通过【迭代器.remove()方法】时 ,快照的状态也发生了改变。保持和集合的真实状态一致。
- 集合结构只要发生改变,迭代器必须重新获取.
package Advance.gather;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionTest06 {
public static void main(String[] args) {
Collection c =new ArrayList();
//获取迭代器,错误,此时尚未添加元素,获取的迭代器
//指向集合中没有元素的情况
//集合结构只要发生改变,迭代器必须重新获取
//Iterator it =c.iterator();
c.add(1);
c.add(2);
c.add(3);
Iterator it =c.iterator();
while(it.hasNext()) {
Object obj = it.next();
//删除元素
//删除元素之后,集合的结构发生变化,应该重新获取迭代器
//但是循环到下一次并没有重新获取迭代器,所以出现异常
//c.remove(obj);
System.out.println(obj);
}
}
}
contains深入理解:底层调用equals
- contains是判断集合中是否包含某个元素的方法
- 底层的运行原理:调用equals方法
- 即:如果放在集合中的元素,是自己创建的引用类型,Student类、teacher类,需要重写equals方法!!!
package Advance.gather;
import java.util.*;
/**
* @author 衣鱼
* 深入理解Collection集合的contains方法
* boolean contains(Object o) //判断集合中是否包含某个对象o
*/
public class CollectionTest04 {
public static void main(String[] args) {
//创建Collection对象
Collection c=new ArrayList();
String s1 = new String("abc");
c.add(s1);
String s2 = new String("def");
c.add(s2);
System.out.println("元素的个数是"+c.size());
String x =new String("abc");
/**问题:c集合是否包括x?
包含的含义:
c集合所指向的ArrayList中,是否添加了X——没有添加,如果contains是对比x,那么结果会输出false
c集合所指向的ArrayList中,是否add了引用x所指向的对象”abc“ —— x 和 s1 都是指向“abc”的引用
*/
System.out.println(c.contains(x)); //true
x.equals(s1);
/**
* String重写的equals方法不比较内存地址,比较的是引用所指向的对象(内容)
* 输出实验结果表明,contains方法底层调用了equals。
* */
System.out.println(c.contains(x)); //true
}
}
remove底层调用equals方法!!
package Advance.gather;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author 衣鱼
* remove()
*/
public class CollectionTest05 {
public static void main(String[] args) {
//创建Collection对象
Collection c=new ArrayList();
String s1 = new String("hello");
c.add(s1);
String s2 = new String("hello");
//删除s2
c.remove(s2);
//
System.out.println("元素的个数是"+c.size());
}
}
list
- list接口
- 存储元素特点:有序可重复 ,有下标,从0开始 以1递增。
- list是Collection的子接口,List的特有方法
- E get(int index) //利用下标获取元素,因为list集合拥有下标,所以list有自己特殊的遍历方式——下标遍历。
- int indexOf(Object o) //获取指定对象第一次出现的索引
- E set(int index, E element) //修改指定目标的元素
package Advance.gather;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* @author 衣鱼
* List特有方法:
* E get(int index)
* int indexOf(Object o)
* E set(int index, E element)
*/
public class ListTest01 {
public static void main(String[] args) {
List myList = new ArrayList();
myList.add("A");
myList.add("B");
myList.add("C");
myList.add("D");
//在列表指定位置添加元素
myList.add(1,"KING"); //在下标1处添加“KING”
//迭代
Iterator it = myList.iterator();
while(it.hasNext()) {
Object elt = it.next();
System.out.println(elt);
}
//根据下标获取元素
Object o =myList.get(1);
System.out.println(o);
//List有下标,所以List集合可以根据下标进行遍历
for(int i =0;i<myList.size();i++) {
Object fristObj = myList.get(i);
System.out.print(fristObj+"\t");
}
System.out.println();
//获取指定对象第一次出现的索引
System.out.println(myList.indexOf("KING")); //1
//获取指定对象最后一次出现处的索引
System.out.println(myList.lastIndexOf("C")); //3
//删除指定下标的元素
myList.remove(1);
for(int i =0;i<myList.size();i++) {
Object fristObj = myList.get(i);
System.out.print(fristObj+"\t");
}
//修改指定目标的元素
myList.set(2, "soft");
for(int i =0;i<myList.size();i++) {
Object fristObj = myList.get(i);
System.out.print(fristObj+"\t");
}
}
}
ArrayList
- ArrayList初始化容量是10(底层先创建一个长度为0的数组,当添加第一个元素的时候,初始化容量10)
- ArrayList集合的扩容是原容量的1.5倍。是原容量的二进制向右移一位。
- ArrayList底层是Object类型的数组,优化:尽可能少的扩容,因为数组扩容效率比较低,建议预先估计所需容量,定义预估计的容量。 List list1 =new ArrayList(200); 减少扩容次数。
- ArrayList构造方法可以将Collection转化为ArrayList。
- ArrayList(Collection<? extends E> c) //构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
- ArrayList(Collection<? extends E> c) //构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
package Advance.gather;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
public class ArrayListTest01 {
public static void main(String[] args) {
//默认初始化容量是10
List list1 =new ArrayList();
//指定初始化容量
List list2 =new ArrayList(100);
//创建HashSet集合
Collection c =new HashSet();
c.add(100);
c.add(200);
c.add(900);
c.add(50);
//HashSet集合转换为List集合
List list3 = new ArrayList(c);
//循环输出转换后的list3集合
for(int i =0;i<list3.size();i++) {
Object obj =list3.get(i);
System.out.println(obj);
}
}
}
LinkList
-
linkList实际上底层是双向链表,具有链表的属性
- 链表优点:由于链表的元素在存储空间内存地址上不是连续的,所以随机增删不会有大量的元素移动,因此随机增删效率较高
- 链表缺点:不能通过数学表达式计算找到元素的内存地址,每一次查找都是从头节点开始遍历,直到找到为止,所以链表的查找/检索效率低。
-
单向链表
vector
-
Vector底层是一个数组,初始容量是10。
-
Vector扩容是原容量是2倍:10——20——40——80
-
Vector所有方法中都是线程同步的,都带有synchronized关键字,是线程安全的,但是效率较低
-
如何将一个线程不安全的ArrayList集合转化成线程安全的
- 使用集合工具类:java.util.Collections;
- 使用集合工具类:java.util.Collections;
泛型
-
JDK5.0之后 推出的新特性
-
泛型属于编译期间的新特性
-
使用泛型之后的优点
- 集合存储的元素类型统一
- 从集合中取出的元素类型是泛型的指定类型,不需要大规模的“向下转型”
-
使用泛型的缺点:导致集合存储元素缺乏多样性
-
List myList = new ArrayList(); 在JDK8之后,泛型引入了自动类型推断机制(钻石表达式)—— List myList = new ArrayList<>();
package Advance.gather;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class GenericTest01 {
public static void main(String[] args) {
//未使用泛型之前
/*
//创建集合
List myList = new ArrayList();
//构造对象
Cat c = new Cat();
Brid b = new Brid();
//将对象放入集合当中
myList.add(c);
myList.add(b);
myList.add(1);
//遍历集合,使集合中的所有动物移动
Iterator it = myList.iterator();
while(it.hasNext()) {
//Animal a =it.next(); //错误
Object obj = it.next(); //使用迭代器取出的就是Object类型
//obj中没有move方法,无法直接调用,需要向下转型
if (obj instanceof Animal) {
Animal a = (Animal) obj;
a.move();
}
}
*/
//使用泛型之后
//使用泛型指定集合中的类型
//List<Animal> :List集合中只允许存储Animal类型的数据 ——类型更统一
List<Animal> myList = new ArrayList<Animal>();
//指定完成后,说明myList中只能存储Animal,不能存储String等其他类型,否则报错
//myList.add("1"); //错误
Cat c = new Cat();
Brid b = new Brid();
myList.add(c);
myList.add(b);
//迭代器迭代Animal类型
Iterator<Animal> it = myList.iterator();
while(it.hasNext()) {
//所有动物移动
//Animal a = it.next();
//a.move();
//猫抓老鼠,鸟儿飞翔——仍需要转型
Animal a = it.next();
if(a instanceof Cat) {
((Cat) a).catchmouse();
}
if(a instanceof Brid){
((Brid)a).fly();
}
}
}
}
//父类
class Animal{
public void move() {
System.out.println("动物在移动!");
}
}
class Cat extends Animal{
public void catchmouse() {
System.out.println("猫在捉老鼠!");
}
}
class Brid extends Animal{
public void fly() {
System.out.println("鸟儿在飞翔!");
}
}
自定义泛型
foreach 增强for循环
-
JDK5之后的新特性
-
语法:
-
for(元素类型 变量名 : 数组或集合){ //变量名代表是数组/集合中的每个元素
System.out.println(变量名);
}
public class GennericTest03 {
public static void main(String[] args) {
int[] arr = {23,425,664,25,2448,2468};
//遍历数组 (普通for循环)
for(int i =0;i<arr.length ;i++) {
System.out.println(arr[i]);
}
System.out.println("===========================");
//foreach 增强for循环
//foreach缺点:没有下标
/*语法:
* for(元素类型 变量名 : 数组或集合){
* System.out.println(变量名);
* }
* */
for(int data:arr) {
//data 代表是数组中的每个元素
System.out.println(data);
}
}
}
- 集合使用foreach
import java.util.ArrayList;
import java.util.List;
//集合使用foreach
public class GennericTest04 {
public static void main(String[] args) {
//创建集合
List<String> myList = new ArrayList<>();
//添加元素
myList.add("asd");
myList.add("fgh");
myList.add("jkl");
myList.add("qaz");
//遍历集合
for(String data : myList) {
System.out.println(data);
}
}
}
Set
- Set集合存储元素的特点:无序不可重复——见例一
- 无序:存进去的顺序和取出的顺序不一定相同,Set集合没有下标
- 不可重复:存进去1,不能再次存储1
- SortedSet集合存储元素的特点:由于继承Set集合,所以他的特点是无序不可重复。但是放在SortedSet集合中的元素可以自动排序,称为可排序集合,放到该集合的元素是自动按照大小顺序排序的。
- 可排序:可以按照大小顺序排序。
- HashSet 的add方法底层是HashMap的key部分
- TreeSet的add方法底层是TreeMap的key部分
HashSet
- HashSet初始化容量为16,初始化建议为2 的倍数。扩容是原容量*2+1.
TreeSet
- TreeSet集合底层实际上是一个TreeMap
- TreeMap集合底层是一个二叉树
- 放到TreeSet集合的元素等同于放到TreeMap集合的Key部分
- TreeSet集合中的元素:无序不可重复,但是可以按照元素大小顺序进行自动排序,称为可排序集合——数据库查询时,升序或者降序排列。
- TreeSet无法对自定义的类型进行排序。程序运行出现异常:java.lang.ClassCastException :Advance.gather.Person cannot be cast to java.lang.Comparable
- 对自定义的类型排序的两个方法:Comparable接口实现、Comparator接口实现
- 当规则不会发生改变的时候,或者说比较规则只有一个的时候,适合使用Comparable
- 当规则有多个,并且多个规则之间频繁切换,适用Comparator接口
排序Comparable接口实现
- compareTo重写前
package Advance.gather;
//compareTo重写前
import java.util.TreeSet;
/**
* TreeSet对自定义的类型不能排序
* 因为没有指定Person对象之间的比较规则
* 程序运行出现异常:java.lang.ClassCastException :Advance.gather.Person cannot be cast to java.lang.Comparable
* */
public class TreeSetTest01 {
public static void main(String[] args) {
//生成对象
Person p1 = new Person(22);
Person p2 = new Person(52);
Person p3 = new Person(16);
Person p4 = new Person(42);
//创建TreeSet集合
TreeSet<Person> person = new TreeSet<>();
//添加元素
person.add(p1); //TreeSet调用add方法,底层调用TreeMap的put方法
person.add(p2);
person.add(p3);
person.add(p4);
//遍历集合
for(Person p : person) {
System.out.println(p); //输出的是Set集合person的元素 每个元素都是Person
//输出的时候调用toString方法,需要重写该方法
}
}
}
class Person{
int age;
public Person(int age) {
this.age=age;
}
//重写toString方法
public String toString() {
return "person[age="+age+"]";
}
}
-
compareTo重写后
- 需要在compareTo方法中编写比较的逻辑:告诉编译器按照什么进行比较
- k.compareTo(t.key)
- 拿着参数k和集合中的每一个k进行比较,返回值:=0、<0、>0、
-
返回0 表示相同 value会覆盖
-
返回>0 会继续在右子树上找
-
返回<0 会继续在左子树上找
package Advance.gather;
import java.util.TreeSet;
/**
* TreeSet对自定义的类型不能排序
* 因为没有指定Person对象之间的比较规则
* 程序运行出现异常:java.lang.ClassCastException :Advance.gather.Person cannot be cast to java.lang.Comparable
* */
public class TreeSetTest02 {
public static void main(String[] args) {
//生成对象
Person p1 = new Person(22);
Person p2 = new Person(52);
Person p3 = new Person(16);
Person p4 = new Person(42);
//创建TreeSet集合
TreeSet<Person> person = new TreeSet<>();
//添加元素
person.add(p1); //TreeSet调用add方法,底层调用TreeMap的put方法
person.add(p2);
person.add(p3);
person.add(p4);
//遍历集合
for(Person p : person) {
System.out.println(p); //输出的是Set集合person的元素 每个元素都是Person
//输出的时候调用toString方法,需要重写该方法
}
}
}
//放在TreeSet集合的元素需要实现java.lang.Comparable接口
//实现compareTo方法 equals可以不写
class Person implements Comparable<Person>{ //实现接口
int age;
public Person(int age) {
this.age=age;
}
//重写toString方法
public String toString() {
return "person[age="+age+"]";
}
/**
* 需要在compareTo方法中编写比较的逻辑:告诉编译器按照什么进行比较
* k.compareTo(t.key)
* 拿着参数k和集合中的每一个k进行比较,返回值:=0、<0、>0、
* 返回0 表示相同 value会覆盖
* 返回>0 会继续在右子树上找
* 返回<0 会继续在左子树上找
* */
@Override
public int compareTo(Person o) { //o1.compareTo(o2);
//o1就是this
//o2就是传入的o
return this.age-o.age;
}
}
排序Comparator接口实现
- 单独编写一个比较器
- 比较器实现java.util.Comparator接口
- Comparable是java.lang包下的 。Comparator是java.util包下的
package Advance.gather;
import java.util.Comparator;
import java.util.TreeSet;
/**
* TreeSet集合中元素可排序的第二种方式:使用比较器
*
* */
public class TreeSetTest03 {
public static void main(String[] args) {
//创建Set集合时,需要使用比较器
//TreeSet<Customer> Customer = new TreeSet<>(); //未调用编写的比较器
//给构造方法传递一个比较器
TreeSet<Customer> customer = new TreeSet<>(new CustomerComparator());
customer.add(new Customer(25));
customer.add(new Customer(54));
customer.add(new Customer(15));
customer.add(new Customer(9));
for(Customer c : customer) {
System.out.println(c);
}
}
}
class Customer{
int age;
public Customer(int age) {
this.age=age;
}
//重写toString方法
public String toString() {
return "Customer [age ="+age+"]";
}
}
//单独编写一个比较器
//比较器实现java.util.Comparator接口
//Comparable是java.lang包下的 。Comparator是java.util包下的
class CustomerComparator implements Comparator<Customer>{
public int compare(Customer o1, Customer o2) {
//指定比较规则:按照年龄排序
return o1.age-o2.age;
}
}
Collections 集合工具类
- Collection 属于java.util 集合接口
- Collections 属于工具类 ,方便集合操作
- 转换成线程安全
- 排序
package Advance.gather;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class CollectionsTest01 {
public static void main(String[] args) {
//ArrayList集合不是线程安全的
List<String> list = new ArrayList<>();
//转换为线程安全的
Collections.synchronizedList(list);
//排序:sort方法针对List集合
//对List集合进行排序,需要确保List集合实现了Comparable接口
Collections.sort(list);
}
}
Map详解
- 常用方法
- boolean containsKey(Object key)
- boolean containsValue(Object value)
- boolean isEmpty() //如果此映射未包含键-值映射关系,则返回 true。
- Set<Map.Entry<K,V>> entrySet() // 返回此映射中包含的映射关系的 Set 视图。——将Map集合转为Set集合,转换成的Set集合元素类型为Map.Entry<K,V> 【Map的静态内部类】
- V get(Object key) //返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。——通过Key 获取value。
- void clear() //从此映射中移除所有映射关系(可选操作)。——清空集合
- Set keySet() // 返回此映射中包含的键的 Set 视图。
- V remove(Object key) //如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
- int size() //返回此映射中的键-值映射关系数。
- V put(K key, V value) //将指定的值与此映射中的指定键关联(可选操作)——添加键值对
package Advance.gather;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class MapTest01 {
public static void main(String[] args) {
//创建Map集合
Map<Integer ,String> maMap = new HashMap<>();
//添加元素
maMap.put(1,"zhangsan");
maMap.put(2,"lisi");
maMap.put(3,"wangwu");
maMap.put(4,"zhaoliu");
maMap.put(5,"zhangsan");
//通过key获取value
String str = maMap.get(1);
System.out.println("键“1”对应的值为"+str);
//获取键值对的数量
System.out.println("键值对的数量 :"+maMap.size());
//判断是否包含某个键
System.out.println(maMap.containsKey(5));
//判断是否包含某个值
System.out.println(maMap.containsValue("zhangsan"));
//通过键删除键值对
maMap.remove(1);
//获取所有的value
Collection<String> value = maMap.values();
for(String s : value) {
System.out.println(s);
}
}
}
☆☆☆Map遍历☆☆☆
- 通过key值 通过获取key值,遍历所有的value
package Advance.gather;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapTest02 {
public static void main(String[] args) {
//方法一:获取key值,遍历所有的value
//创建Map集合
Map<Integer ,String> map = new HashMap<>();
//添加元素
map.put(1,"zhangsan");
map.put(2,"lisi");
map.put(3,"wangwu");
map.put(4,"zhaoliu");
map.put(5,"zhangsan");
//获取所有key值
Set<Integer> keys = map.keySet();
//遍历key
//迭代器
Iterator<Integer> it = keys.iterator();
while(it.hasNext()) {
Integer key =it.next(); //迭代获取key值
String value = map.get(key); //由map中key值获取vlaue值
System.out.println(value);
}
//foreach循环
for(Integer key :keys) {
String vlaue2 = map.get(key);
System.out.println(vlaue2);
}
//方法二:Set<Map.Entry<K,V>> entrySet()
//将Map集合直接全部转换为Set集合
//Set集合中元素的类型:Map.entry
Set<Map.Entry<Integer, String>> set = map.entrySet();
//遍历set
Iterator<Map.Entry<Integer, String>> its = set.iterator();
while(its.hasNext()) {
Map.Entry<Integer, String> entry =its.next(); //取出了的一个结点:node对象
//调用结点entry的get方法 得到key、value
Integer key = entry.getKey();
String vlaue = entry.getValue();
}
//foreach循环——————————效率较高
for(Map.Entry<Integer, String> entry : set) {
System.out.println(entry.getKey()+"-------->"+entry.getValue());
}
}
}
- Map遍历第二种方法 :Set<Map.Entry<K,V>> entrySet()
HashMap
- HashMap集合底层是哈希表/散列表的数据结构,且key值和value都可以为null。但是HashTable的key、value都不能为null,会出现空指针异常。
- 哈希表:
- 哈希表是一个数组和单向链表的结合体
- 数组:在查询方面效率高,随机增删方面效率低
- 单向链表:在随机增删方面效率高,查询效率低
- 哈希表集两者之长,发挥优点。
- HashMap集合的默认初始化容量为16,默认加载因子是0.75。意为当HashMap集合底层数组容量达到75%的时候,数组开始扩容。扩容之后的容量是原来容量的2倍。
- HashMap集合初始化最好是2的幂数,提高hash的存取效率。
- 在JDK8之后,如果Hash表单向链表的元素超过8个,单向链表会变成红黑树数据结构。当红黑树上的结点小于6时,红黑树数据结构会变回单向链表。
- HashMap的源代码
- HashMap的存取元素的原理
- 重点:放在HashMap集合的key部分元素,以及放在HashSet集合中的元素,都需要重写HashCode和equals方法。——编译器生成
- HashCode是生成哈希值的,哈希值用作数组下标,所以存取时,先调用hashCode,当数组下标一样时,进行同一数组下标的链表equals比较。
- 如果一个类的equals方法重写了,那么hashCode方法必须重写。如果该类的equals结果返回ture,那么hashCode返回结果应当一样。
HashTable
- HashTable是线程安全的
- HashTable和HashMap一样底层都是哈希表
- HashTable初始化容量为11,默认加载因子0.75。HashTable的扩容是原容量*2+1.【即原容量的二进制右移一位】
- HashTable是线程安全的
- properties
package Advance.gather;
import java.util.Properties;
/**
* Properties是Map集合,被称为属性类对象
* 继承HashTable,是线程安全的。
* Properties的key和value都是String类型
*
* 掌握properties两个方法:存、取
* */
public class PropertiesTest01 {
public static void main(String[] args) {
Properties pro = new Properties();
//存:.setProperty
pro.setProperty("user1", "qwerthbujbue");
pro.setProperty("user2", "qwwatghgujbue");
pro.setProperty("user3", "waghbvrjshgf");
pro.setProperty("user4", "thguytlkjhgfeu");
//取:通过key获取value
String user1 = pro.getProperty("user1");
String user2 = pro.getProperty("user2");
String user3 = pro.getProperty("user3");
String user4 = pro.getProperty("user4");
System.out.println(user1);
}
}