集合到底是什么
- 数组就是一个集合 集合实际上就是一个容器 可以来容纳其他类型的数据
集合与数组的区别
- 数组的长度是固定的 集合的长度是可变的
- 数组中存储的是同一类型的元素,可以存储基本数据类型值。
- 集合存储的都是对象。而且对象的类型可以不一致。
主要内容
- Collection集合
- 迭代器
- 增强for
- List集合
- Set集合
学习目标
- [ ] 能够使用迭代器对集合进行取元素
- [ ] 能够使用集合存储自定义类型
- [ ] 能够说出什么是集合
- [ ] 能够说出集合与数组的区别
- [ ] 能够说出ArrayList、LinkedList、Vector区别
- [ ] 够说出Set集合各种实现类的区别
- [ ] 能够说出Collection和Map集合的区别
- [ ] 说出Map集合的常用功能
- [ ] 能够遍历Map集合
- [ ] 能够说出各种Map集合实现类的区别
- [ ] 能够简单阐述HashMap的底层实现
- [ ] 能够查询和使用集合工具类的相关方法
- [ ] 能够说出Set与Map的关系
集合框架
Collection接口:单列集合 用来存储一个一个的对象
List接口:有序的 可重复 支持索引
- ArrayList:作为List接口的主要实现类;线程不安全 效率高 底层使用数组存储
- LinkedList:底层使用双向链表存储 线程不安全 执行效率高
- Vector:作为List接口的古老实现类;线程安全的 效率低 底层使用数组存储
- Set接口:无序的 不可重复的数据
HashSet:作为Set接口的主要实现类 线程不安全的 可以存储NULL值
- LinkedHashSet:有序 作为HashSet的子类 遍历内部数据时 可以按照添加的顺序遍历 频繁的遍历操作 效率高与HashSet
- TreeSet:添加数据要求是同一类型
Map接口:双列集合 用来存储一对一对的数据(Key - value)
HashMap:作为Map的主要实现类;线程不安全 效率高 存储Null的Key和value
- LinkedHashMap:在HashMap原有的基础上 添加了一对儿指针,指向前一个和后一个元素
- TreeMap:按照添加的Key-value进行排序 实现排序遍历
- Hashtable:作为古老的实现类;线程安全 效率低 不能存储Null的Key和value
- Properties:用来处理配置文件 Key和value都是String类型
Collection 常用功能
属性 | 说明 |
---|---|
add | 添加元素对象到当前集合中 |
addAll | 添加新集合中的所有元素对象到当前集合中 |
remove | 删除第一个找到的与obj对象equals返回true的元素 |
removeAll | 删除所有与coll集合中相同的元素 |
isEmpty | 判断当前集合是否为空集合 |
contains | 判断当前集合中是否存在一个与obj对象equals返回true的元素 |
containsAll | 判断c集合中的元素是否在当前集合中都存在 |
size | 查询当前集合中实际存储的元素个数 |
toArray | 集合转换为数组 |
Arrays.asList | 数组转换为集合 |
hashCode | 查询当前对象的哈希值 |
Collection集合基本使用
package Collection01;
import java.util.*;
public class CollectionTest {
public static void main(String[] args) {
//1.添加元素
Collection coll = new ArrayList();
coll.add("张三");
coll.add(new String("Tom"));
coll.add("李四");
Collection coll1 = new ArrayList();
coll1.add("likedx");
coll1.add("likedx1");
coll1.add("李哈哈");
coll1.add("李四");
//添加新集合中的所有对象到当前集合中
coll.addAll(coll1);
System.out.println(coll);
//2.删除元素
//coll.remove("张三");
//删除所有并且与coll集合中相同的元素
//coll.removeAll(coll1);
System.out.println(coll);
//3.判断元素
System.out.println("判断coll是否为空的集合" + coll.isEmpty());
System.out.println("判断张三是否存在Coll集合中" + coll.contains("张三"));
System.out.println("判断coll1集合中的元素是否在当前集合中都存在" + coll.containsAll(coll1));
//4.查询
System.out.println("储存元素的个数为:" + coll.size());
//集合转换为数组
Object[] objects = coll.toArray();
//遍历数组
for (int i = 0; i < objects.length; i++) {
System.out.println(objects[i]);
}
System.out.println("=======================");
//数组转换为集合Arrays.asList(数组名).var
List<Object> objects1 = Arrays.asList(objects);
System.out.println(objects1);
//查询当前对象的哈希值
System.out.println(coll.hashCode());
System.out.println("==============================");
Collection collection = new ArrayList();
Person p = new Person("张三",20);
collection.add(p);
collection.add(new Person("likedx",18));
collection.add("Tom");
//判断Tom是否在coll集合当中
System.out.println(coll.contains(new String("Tom")));
//判断时会调用obj对象所在类的equals 不重写Person类equals方法为false
System.out.println(coll.contains(new Person("likedx",18)));
}
}
class Person{
private String name;
private int age;
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 +
'}';
}
/* public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}*/
}
Iterator迭代器
Iterator接口
迭代:Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出
基本功能
方法 | 说明 |
---|---|
remove | 删除元素 |
hasNext | 判断元素 |
next | 输出元素 |
package Collection01;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorTest {
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add("One");
coll.add("Two");
coll.add("Three");
coll.add("Four");
System.out.println("当前的数据是:" + coll);
//创建迭代器对象
Iterator iterator = coll.iterator();
System.out.println(iterator.next());
System.out.println(iterator.next());
System.out.println(iterator.next());
System.out.println(iterator.next());
//输出的次数大于集合中的个数会导致无法获取到下一个元素 出现NoSuchElementException异常
//System.out.println(iterator.next());
//遍历集合 判断有没有元素 有就取出来 继续判断直到结束
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
//删除迭代器中的所有元素
iterator.remove();
//再次访问会出错 出现NoSuchElementException异常
//System.out.println(iterator.next());
}
}
增强for
增强for循环(也称for each循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。
for(元素的数据类型 变量 : Collection集合or数组){
//遍历的元素
}
- 遍历集合
public class For_each {
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add("zhangsan");
coll.add("lisi");
coll.add("wangwu");
coll.add("zhaoliu");
//遍历集合
for (Object obj : coll) {
System.out.println(obj);
}
}
}
- 遍历数组
public class For_each {
public static void main(String[] args) {
//遍历数组
int [] arr = new int[]{1,2,3,4,5,6,7,8};
for (int i : arr) {
System.out.println(i);
}
String [] str = new String[]{"zhangsan","lisi","wangwu","zhaoliu"};
for (String i : str) {
System.out.println(i);
}
}
}
- 练习题
public class For_each {
public static void main(String[] args) {
String [] arr = new String[]{"MM","MM","MM"};
/* for (int i = 0; i < arr.length; i++) {
arr[i] = "GG";
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]); //输出GG
}*/
for (String str : arr) {
str = "GG"; //此str非str str为局部变量
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);//输出MM
}
}
}
List集合
特点:
- 作为List接口的主要实现类;线程不安全 效率高 底层使用数组存储
- 元素有序 可重复
List接口中常用方法
方法 | 说明 |
---|---|
add(Object obj) | 增 |
remove(int index) / remove(Object ele) | 删 |
set(int index,Object ele) | 改 |
get(int index) | 查 |
add(int index,Object ele) | 插 |
size() | 长度 |
Iterator迭代方式 增强for循环 普通的循环 | 遍历 |
indexof(Object o) | 字符串返回索引 |
lastIndexOf(Object o) | 重复字符串返回索引 |
contains(Object o) | 包含某字符串 |
isEmpty | 是否为空 |
addAll(Collection c) | 插入新集合 |
removeAll(Collection c) | 删除新集合 |
clear | 清空 |
clone | 克隆 |
toArray | 集合转数组 |
Arrays.asList(集合的变量) | 数组转集合 |
public class ArrayList_Test {
public static void main(String[] args) {
ArrayList arr = new ArrayList();
//增加数据
arr.add("zhangsan");
arr.add("lisi");
arr.add("wangwu");
//删除数据
Object remove = arr.remove(1);
System.out.println(remove); //查看删除的数据
boolean lisi = arr.remove("zhangsan");
System.out.println(lisi); //返回布尔类型 判断是否删除成功
arr.add("zhaoliu");
arr.add("aa");
arr.add("bb");
//修改数据
Object likedx = arr.set(0, "likedx"); //将下标0是wangwu修改为likedx
System.out.println(likedx); //查看修改前的数据
//查询数据
Object o = arr.get(0);
System.out.println(o);
System.out.println(arr);
//集合转换数组
Object[] objects = arr.toArray();
//数组转换集合
List<Object> objects1 = Arrays.asList(objects);
System.out.println("*************************");
//遍历集合方式一:普通遍历
/* for (int i = 0; i < arr.size(); i++) {
System.out.println(arr.get(i));
}*/
//方式二:增强for
/* for (Object obj : arr) {
System.out.println(obj);
}*/
//方式三:iterator迭代器
Iterator iterator = arr.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
package Test1;
public class Cat {
private String name;
public Cat() {
}
public Cat(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
'}';
}
}
public class ArrayTest {
public static void main(String[] args) {
List list = new ArrayList();
//添加4只小猫
list.add(new Cat("英短猫"));
list.add(new Cat("缅因猫"));
list.add(new Cat("布偶猫"));
list.add(new Cat("狸花猫"));
//查询有几只小猫
System.out.println("小猫数量:" + list.size()); //4
//删除小猫
list.remove(0);
System.out.println("小猫数量:" + list.size()); //3
//遍历小猫
for (int i = 0; i < list.size(); i++) {
//向下转型
Cat cat = (Cat) list.get(i);
System.out.print(cat.getName() + "\t"); //缅因猫 布偶猫 狸花猫
}
System.out.println("");
//修改小猫
list.set(0,new Cat("蓝猫"));
System.out.println("修改的小猫为:");
for (int i = 0; i < list.size(); i++) {
//向下转型
Cat cat = (Cat) list.get(i);
System.out.println(cat.getName()); //蓝猫 布偶猫 狸花猫
}
}
}
ArrayList底层原理
JDK1.7:
- ArrayList arr = new ArrayList(); //底层创建了长度是10的Object[]数组elementData
- 如果elementData数组容量不够 那就扩容 默认情况下扩容为原来的1.5倍,同时需要将原有数组中的数据复制到新的数组中
JDK1.8:
- ArrayList arr = new ArrayList(); //底层Object[]elementData初始化为0 没有创建长度
- arr.add(1); //第一次调用add时 底层才创建了长度10的数组,并将数据添加到elementData
- 如果elementData数组容量不够 那就扩容 默认情况下扩容为原来的1.5倍,同时需要将原有数组中的数据复制到新的数组中
LinkedList集合
特点:
- 底层使用双向链表存储
- 线程不安全
- 频繁的插入 删除 使用此类的效率比ArrayList高
- 可以包含重复的元素
方法 | 说明 |
---|---|
getFirst | 获取头部信息 |
getLast | 获取尾部信息 |
addFirst | 指定头部添加信息 |
addLast | 指定尾部添加信息 |
remove | 默认删除第一个 |
removeFirst | 删除头部信息 |
removeLast | 删除尾部信息 |
push(Object e) | 添加数据 |
pop | 弹出数据 |
public class Linkedlist_Test {
public static void main(String[] args) {
LinkedList list = new LinkedList();
//增删改查也比较重要 用法一样
//方式一: 入栈
list.add(1);
list.add(2);
list.add(3);
System.out.println(list);
//弹栈
System.out.println(list.pop());
System.out.println(list.pop());
System.out.println(list.pop());
//栈空了会 报错 NoSuchElementException
//System.out.println(list.pop());
System.out.println("========================");
//方式二:入栈 先进后出 因在尾部last
list.addLast(1);
list.addLast(2);
list.addLast(3);
//弹栈
System.out.println(list.removeLast());
System.out.println(list.removeLast());
System.out.println(list.removeLast());
//栈空了会 报错 NoSuchElementException
//System.out.println(list.removeLast());
}
}
Set集合
特点:
- 存储无序的 不可重复的数据
- Set的常用实现类有:HashSet、TreeSet、LinkedHashSet。
- Set集合支持的遍历方式和Collection集合一样:foreach和Iterator。
- 向set中添加数据,所有的类一定要重写hashCode和equals实现去重
HashSet
- 无序性 存储的数据在底层数组中并非按照数组的索引顺序添加 而是根据数据的哈希值添加的
- Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
- 作为Set主要实现类 线程不安全的 可以存储NULL值
注意:
HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。因此,存储到HashSet的元素要重写hashCode和equals方法。
package Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
Set set = new HashSet();
set.add(122);
set.add("AA");
set.add("BB");
set.add("CC");
set.add(456);
set.add(123);
set.add(new User1("张三",10));
set.add(new User1("张三",10));
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
class User1{
private String name;
private int age;
public User1() {
}
public User1(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 "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
/* @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User1 user1 = (User1) o;
return age == user1.age && Objects.equals(name, user1.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}*/
}
LinkedHashSet
特点:
- LinkedHashSet作为HashSet的子类 在添加数据的同时 每个数据还维护了两个引用(两个引用指前和后) 记录当前数据前一个数据和后一个数据
- 频繁遍历 效率高 有序不可重复
package Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
public class SetTest02 {
public static void main(String[] args) {
Set set = new LinkedHashSet();
set.add("zhang");
set.add(123);
set.add(4521);
set.add("lisi");
set.add("wangwu");
set.add("wangwu");
System.out.println("元素的个数为:" + set.size());
for (Object obj : set) {
System.out.println(obj);
}
}
}
TreeSet
特点:
- 不允许重复
- 实现排序
- 自然排序或定制排序
- 如果使用的是自然排序,则通过调用实现的compareTo方法
- 如果使用的是定制排序,则通过调用比较器的compare方法
如何实现去重的?
- 如果使用的是自然排序,则通过调用实现的compareTo方法
- 如果使用的是定制排序,则通过调用比较器的compare方法
如何排序?
方式一:自然排序
- 实现Comparable接口,并重写compareTo方法
方式二:定制排序
- 实现Comparator接口,重写compare方法
自然排序
- 根据姓名进行自然排序
public class TreeSet_Test05 {
public static void main(String[] args) {
Set<Animal> set = new TreeSet<>();
set.add(new Animal("asd"));
set.add(new Animal("vxc"));
set.add(new Animal("bdfa"));
set.add(new Animal("zwedsa"));
Iterator<Animal> iterator = set.iterator();
while (iterator.hasNext()) {
Animal next = iterator.next();
System.out.println(next);
}
}
}
class Animal implements Comparable<Animal>{
private String name;
public Animal() {
}
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
'}';
}
@Override
public int compareTo(Animal o) {
//升序
return this.name.compareTo(o.name);
//降序
//return -this.name.compareTo(o.name);
}
}
假设我们有一个类
cat
,它包含两个属性:name
和age
。我们想要按照年龄进行排序:- cat类需要实现Comparable并且重写compareTo方法
public class TreeSet_Test04 {
public static void main(String[] args) {
Set<Cat> set = new TreeSet<>();
set.add(new Cat("狸花猫",1));
set.add(new Cat("蓝猫",3));
set.add(new Cat("博美",2));
Iterator<Cat> iterator = set.iterator();
while (iterator.hasNext()) {
Cat next = iterator.next();
System.out.println(next);
}
}
}
class Cat implements Comparable<Cat>{
private String name;
private int age;
public Cat() {
}
public Cat(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 "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Cat o) {
//根据年龄从高到低进行排序
//return -Integer.compare(age,o.age);
//根据年龄从低到高进行排序
return Integer.compare(this.age,o.age);
}
}
定制排序
根据字符串长度进行排序
- 向set添加数据时其指定类需要实现Comparator接口并重写compare方法
public class StringLengthComparator implements Comparator<String> {
//实现Comparator并重写compare方法
@Override
public int compare(String o1, String o2) {
return Integer.compare(o1.length(),o2.length());
}
}
public class TreeSet_Test {
public static void main(String[] args) {
//在使用TreeSet时将StringLengthComparator传递给他的构造参数
//根据字符串的长度进行升序排序
Set set = new TreeSet(new StringLengthComparator());
set.add("a123");
set.add("a");
set.add("bcdfg");
set.add("12");
set.add("b123"); //只会按照插入的顺序进行排序
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
//a a12 a123 bcdfg
}
}
}
假设我们有一个
Student
类,包含name
和score
两个属性。现在要按照学生分数从高到低排序:- 学生类需要重写tostring方法
- 分数排序类需要实现implements接口并且实现compare方法
public class TreeSet_Test02 { public static void main(String[] args) { //创建TreeSet的时候传入ScoreComparator构造方法 Set<Student> set = new TreeSet<>(new ScoreComparator()); set.add(new Student("张三",85)); set.add(new Student("李四",78)); set.add(new Student("王五",90)); set.add(new Student("赵六",88)); Iterator<Student> iterator = set.iterator(); while (iterator.hasNext()) { Student next = iterator.next(); System.out.println(next); //Student{name='李四', score=78} //Student{name='张三', score=85} //Student{name='赵六', score=88} //Student{name='王五', score=90} } } } class Student{ private String name; private int score; public Student() { } public Student(String name, int score) { this.name = name; this.score = score; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getScore() { return score; } public void setScore(int score) { this.score = score; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", score=" + score + '}'; } } //分数排序类 实现了Comparator接口 class ScoreComparator implements Comparator<Student>{ @Override public int compare(Student o1, Student o2) { //从高到低 //return -Integer.compare(o1.getScore(),o2.getScore()); //从低到高 return Integer.compare(o1.getScore(),o2.getScore()); } }
组合排序
假设我们有一个
Person
类,包含name
和age
两个属性。我们想要按照年龄升序排序,如果年龄相同,则按照名字升序排序- 年龄类实现Comparator接口重写compare方法对其进行排序
public class TreeSet_Test03 {
public static void main(String[] args) {
Set<Person> set = new TreeSet<>(new AgeNameComparator());
set.add(new Person("阿乐",85));
set.add(new Person("李四",96));
set.add(new Person("王五",70));
set.add(new Person("张三",85));
Iterator<Person> iterator = set.iterator();
while (iterator.hasNext()) {
Person next = iterator.next();
System.out.println(next);
}
}
}
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 +
'}';
}
}
class AgeNameComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
int result = Integer.compare(o1.getAge(),o2.getAge());
if (result == 0){
return o1.getName().compareTo(o2.getName());
}
return result;
}
}
Map集合
特点:
- Map和Collection没有继承关系
- Map集合是以Key和Value的方式存储数据 键值对
- map中的集合,元素是成对儿存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值
Map常用方法
属性 | 说明 |
---|---|
put(Object key,Object value) | 添加数据 |
putAll(Map m) | 添加对儿新集合 |
clear() | 清空集合中的数据 |
remove(Object key) | 通过key删除数据 |
get(Object key) | 通过key获取value |
containsKey(Object key) | 判断是否包含某个key(键) |
containsValue(Object value) | 判断是否包含某个value(值) |
isEmpty() | 判断是否为空 |
keySet() | 获取map所有的key 也可以讲key转换为一个集合 |
size() | 获取键值对的个数 |
entrySet() | 将Map集合转换为Set集合 |
values() | 获取所有的value |
Map.Entry | 表示集合中的一个对象的实体key-value |
public class Map_Test {
public static void main(String[] args) {
//创建Map集合对象
Map<Integer,String> map = new HashMap<>();
//向Map集合中添加对象
map.put(1,"zhangsan");
map.put(2,"lisi");
map.put(3,"wangwu");
map.put(4,"zhaoliu");
//通过key删除数据
map.remove(1);
//判断是否包含某个key
System.out.println(map.containsKey(2));
//判断是否包含某个value
System.out.println(map.containsValue("wangwu"));
//通过key获取value
System.out.println(map.get(2));
//获取键值对的数量
System.out.println(map.size());
//获取所有的value
Collection<String> values = map.values();
//遍历value
for (String s : values) {
System.out.println(s);
}
//清空集合
//map.clear();
}
}
Map集合的遍历
基本:
将map转换为set集合 通过node进行遍历 Set<Map.Entry<K, V>> set = map.entrySet(); 效率高
通过set集合遍历key
public class Map_Test {
public static void main(String[] args) {
Map map = new HashMap();
map.put(1,"zhangsan");
map.put(2,"lisi");
map.put(3,"wangwu");
map.put(4,"zhaoliu");
//方式一 迭代器遍历Key
Set keys = map.keySet();
Iterator iterator = keys.iterator();
while (iterator.hasNext()){
System.out.println("Key的值是:" + iterator.next());
}
System.out.println("===================");
//方式二 增强for
Set keys1 = map.keySet();
for (Object obj : keys1) {
System.out.println("Key的值是:" + obj);
}
System.out.println("===================");
}
}
通过key遍历value
public class Map_Test02 {
public static void main(String[] args) {
Map map = new HashMap();
map.put(1,"zhangsan");
map.put(2,"lisi");
map.put(3,"wangwu");
//遍历value
Set keys = map.keySet();
Iterator iterator = keys.iterator();
while (iterator.hasNext()){
Object key = iterator.next();
System.out.println("value的值为:" + map.get(key));
}
System.out.println("====================");
//增强for
Set set1 = map.keySet();
for (Object value : set1) {
System.out.println("value的值为:" + map.get(value));
}
System.out.println("====================");
//方式二
Collection values = map.values();
for (Object value : values){
System.out.println("value的值为:" + value);
}
}
}
遍历集合
例:
public class Map_Test03 {
public static void main(String[] args) {
Map map = new HashMap();
map.put(1,"zhangsan");
map.put(2,"lisi");
map.put(3,"wangwu");
map.put(4,"zhaoliu");
//迭代器遍历集合
Set set = map.entrySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()){
Object obj = iterator.next();
Map.Entry entry = (Map.Entry)obj;
System.out.println(entry.getKey() + "=" + entry.getValue());
}
System.out.println("=================");
//增强for
Set keys = map.entrySet();
for (Object obj : keys) {
Map.Entry entry = (Map.Entry)obj;
System.out.println(entry.getKey() + "=" + entry.getValue());
}
}
}
例:
public class Map_Test04 {
//效率高
public static void main(String[] args) {
Map<Integer,String> map = new HashMap<>();
map.put(1,"张三");
map.put(2,"王五");
map.put(3,"赵六");
//将map集合转换为set集合 通过迭代器方式进行遍历
//将map集合转换为set集合
Set<Map.Entry<Integer, String>> entries = map.entrySet();
//创建一个迭代器对象
Iterator<Map.Entry<Integer, String>> iterator = entries.iterator();
while (iterator.hasNext()){
//每一次取出node 通过node访问key和value
Map.Entry<Integer, String> node = iterator.next();
System.out.println(node.getKey() + "=" + node.getValue());
}
System.out.println("==============");
//增强for
//将map集合转换为set集合
Set<Map.Entry<Integer, String>> entries1 = map.entrySet();
for (Map.Entry<Integer,String> key : entries1) {
System.out.println(key.getKey() + "=" + key.getValue());
}
}
}
HashMap底层实现原理
JDK1.7:
- 实例化后 底层创建了长度是16的一维数组Entry[]数组
- map.put(key1,value1):调用key1的HachCode()计算哈希值,得到在Entry数组中的存放位置
如果此位置上数据为空 则k1v1添加成功
如果不为空 比较key1和已经存在的一个或者多个数据的哈希值
- 如果key1的哈希值和已经存在数据的哈希值不相同 则添加成功
如果key1的哈希值和已经存在的某一个数据的哈希值相同 调用key1所在类的equals(key2)方法比较
- 如果equals()为false:则添加成功
- 如果为true:使用value1替换value2
- 扩容方式:扩容为原来容量的2倍,并将原有数据复制过来
JDK1.8:
- 实例化后 底层没有创建一个长度为16的一维数组Node[]数组
- 首次调用put方法时 底层创建长度为16的数组
- JDK7底层结构:数组+链表
- JDK8底层结构:数组+链表+红黑树
- 当数组的某一个索引位置上的元素以链表形式存在的数据个数>8 并且当前数组长度>64 此时此索引位置上的所有数据改为使用红黑树存储
HashMap和TreeMap有什么区别
- HashMap的key可以为null、TreeMap不可以
Properties属性类
Properties是一个Map集合,Hashtable的子类
Properties的key和value都是String类型
Properties被称为属性类对象 一般用来处理配置文件
属性 | 说明 |
---|---|
setProperty(String key,String value) | 添加元素 |
getProperty(String key) | 通过key获取value |
public class Properties_Test {
//Properties:常用来处理配置文件。key和value都是String类型
public static void main(String[] args) {
Properties pro = new Properties();
pro.setProperty("url","blogdx.com");
pro.setProperty("username","root");
pro.setProperty("password","123");
//通过key获取value
String url = pro.getProperty("url");
System.out.println(url);
System.out.println(pro.getProperty("username"));
System.out.println(pro.getProperty("password"));
}
}
Collections工具类
Collections是一个操作Set、List和Map等集合的工具类
Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法
静态属性 | 说明 |
---|---|
reverse | 翻转list |
shuffle | 随机排序 |
sort | 自然排序 |
swap(list,int i,intj) | 交换list集合中指定索引位置上的两个元素 |
max | 获取最大值 |
min | 获取最小值 |
frequency(Object o) | 获取list集合中元素出现的次数 |
synchronizedList | 将list集合转换为线程安全的 |
public class Collections_Test {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(123);
list.add(123);
list.add(23);
list.add(-13);
list.add(0);
list.add(89);
//翻转list中元素的顺序
Collections.reverse(list);
//对list集合元素进行随机排序
Collections.shuffle(list);
//对list进行自然排序
Collections.sort(list);
//交换list集合中指定索引位置上的两个元素
Collections.swap(list,0,1);
//获取最大值
//System.out.println(Collections.max(list));
//获取最小值
//System.out.println(Collections.min(list));
//获取list集合中123出现的次数
int frequency = Collections.frequency(list, 123);
//synchronizedList:将list转换为线程安全的
List list1 = Collections.synchronizedList(list);
System.out.println(list1);
}
}
斗地主小游戏
package Demo2;
import java.util.*;
public class DouDiZhu {
public static void main(String[] args) {
// 初始化一副牌
List<String> poker = initPoker();
// 洗牌
Collections.shuffle(poker);
// 发牌
Map<Integer, List<String>> players = dealCards(poker);
// 显示手牌
showCards(players);
}
/**
* 初始化一副牌
*/
private static List<String> initPoker() {
List<String> poker = new ArrayList<>();
String[] colors = {"♠", "♥", "♣", "♦"};
String[] numbers = {"2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3"};
for (String color : colors) {
for (String number : numbers) {
poker.add(color + number);
}
}
poker.add("小王");
poker.add("大王");
return poker;
}
/**
* 发牌
*/
private static Map<Integer, List<String>> dealCards(List<String> poker) {
Map<Integer, List<String>> players = new HashMap<>();
// 底牌
List<String> bottom = new ArrayList<>();
// 发牌
for (int i = 0; i < poker.size(); i++) {
String card = poker.get(i);
if (i >= poker.size() - 3) { // 最后三张为底牌
bottom.add(card);
} else {
int playerNum = i % 3 + 1; // 玩家编号
List<String> playerCards = players.computeIfAbsent(playerNum, k -> new ArrayList<>());
playerCards.add(card);
}
}
players.put(0, bottom);
return players;
}
/**
* 显示手牌
*/
private static void showCards(Map<Integer, List<String>> players) {
for (Map.Entry<Integer, List<String>> entry : players.entrySet()) {
Integer key = entry.getKey();
List<String> value = entry.getValue();
System.out.print("玩家" + key + ": ");
for (String s : value) {
System.out.print(s + " ");
}
System.out.println();
}
}
}
initPoker()
方法用于初始化一副扑克牌,包括52张普通牌和2张大小王,返回一个列表对象;dealCards()
方法接收一副已经初始化好的扑克牌,首先创建一个HashMap
对象来存储三个玩家的手牌和三张底牌。之后通过循环遍历牌堆,将前51张牌均分给三个玩家,每个玩家17张牌。最后将最后三张牌作为底牌放入bottom
列表中,并将bottom
列表也放入players
中,编号为0表示底牌;showCards()
方法用于展示每个玩家的手牌和三张底牌。遍历players
,对于每个键值对,输出玩家编号和对应的牌。- 在
main
方法中,首先调用initPoker()
方法来初始化一副牌,然后使用Collections.shuffle()
方法洗牌,再调用dealCards()
方法发牌,最后使用showCards()
方法展示每个玩家的手牌和三张底牌。