Java集合详解
Java集合详解
集合类的特点:
- 提供一种存储空间可变的存储模型,存储的数据容量可以发生改变
集合类的整体构造模式:
集合类名<类型> 集合对象名 = new 集合类名<类型>();
集合类体系结构:
- 集合
- Collection(单列)
- List(可重复)
- ArrayList
- LinkedList
- Set(不可重复)
- HashSet
- TreeSet
- List(可重复)
- Map(双列)
- HashMap
- Collection(单列)
增强for循环
这里介绍for循环的增强型(专门简化数组和Collection集合的遍历)
- 实现Iterator接口的类允许其对象称为增强型for语句的目标
- 它是JDK5之后出现的,其内部原理是一个iterator迭代器
增强for循环格式:
for(元素数据类型 变量名 : 数组/Collection集合){
......(注意:变量名就是元素)
}
迭代器
在讲述集合前,需要了解一下迭代器
迭代器Iterator,集合专用遍历方式
- Iterator
iterator():返回此集合中元素的迭代器,通过集合的Iterator()方式获得 - 迭代器是通过集合的iterator()方法获得的,所以我们说它是依赖集合而存在的,产生迭代器后不能对集合进行修改
Iterator的常用方法:
- E next(): 返回迭代中的下一个元素
- boolean hasNext():如果迭代具有更多元素,则返回true
哈希值
哈希值:是JDK根据对象的地址或字符串或者数字计算出来的int类型的数值
Object类中有一个方法可以获得对象的哈希值:
public int hashCode();返回对象的哈希码值
对象的哈希值特点:
- 同一个对象多次调用hashCode()方法返回的哈希值是一样的
- 默认情况下,不同对象的哈希值是不同的
- 可以通过重写hashCode()方法来使不同对象的哈希值相同
下面给出代码实例:
public class Demo1 {
public static void main(String[] args) {
//比较类的对象的哈希值
Demo2 d1 = new Demo2("HOU",20);
Demo2 d2 = new Demo2("ZHANG",18);
System.out.println(d1.hashCode());
System.out.println(d2.hashCode());
//比较字符串哈希值:
System.out.println("Hello".hashCode());
System.out.println("java".hashCode());
System.out.println("java".hashCode());
}
}
public class Demo2 {
//学生类
String name;
int age;
public Demo2(String name,int age){
this.name = name;
this.age = age;
}
}
编译结果:
460141958
1163157884
69609650
3254818
3254818
Collection集合
Collection集合概述:
- 是单例集合的顶层接口,表示一组对象,这些对象称为Collection的元素
- JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现
Collection创建对象
创建Collection集合的对象:
- 多态的方法
- 具体的实现类ArrayList
创建对象示例代码:
//创建对象
Collection<String> c = new ArrayList<String>();//ArrayList是Collection的子类
Collection集合常用方法
方法名 | 说明 |
---|---|
boolean add(E e) | 添加元素 |
boolean remove(Object o) | 从集合中移除指定的元素 |
void clear() | 情况集合中的元素 |
boolean contains(Object o) | 判断集合是否存在指定元素 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,集合元素的个数 |
下方给出示例代码:
import java.util.ArrayList;
import java.util.Collection;
public class Demo2 {
public static void main(String[] args) {
//创建对象
Collection<String> c = new ArrayList<String>();
//添加元素:
c.add("Hello");
c.add("World");
System.out.println(c);
//删除元素:
c.remove("World");
System.out.println(c);
//全部清空:
c.clear();
System.out.println(c);
//我们再添加一些元素:
c.add("Hello");
c.add("World");
//查找集合中是否存在指定元素:
System.out.println(c.contains("Hello"));
//判断是否为空:
System.out.println(c.isEmpty());
//给出目前集合的长度:
System.out.println(c.size());
}
}
编译结果:
[Hello, World]
[Hello]
[]
true
false
2
Collection集合的遍历
集合遍历一般需要采用迭代器来进行:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Demo3 {
public static void main(String[] args) {
//创建对象
Collection<String> c = new ArrayList<String>();
//添加元素:
c.add("Hello");
c.add("World");
c.add("java");
//设置迭代器:(用集合来创建迭代器)
Iterator<String> it = c.iterator();
//遍历
while(it.hasNext()){
System.out.println(it.next());
}
}
}
编译结果:
Hello
World
java
案例:Collection集合存储学生对象并遍历
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class appliation {
public static void main(String[] args) {
//创建ArrayList对象
Collection<Student> arr = new ArrayList<Student>();
//创建学生对象
Student s1 = new Student("HOU",20);
Student s2 = new Student("DU",22);
Student s3 = new Student("ZHANG",18);
//加入学生对象
arr.add(s1);
arr.add(s2);
arr.add(s3);
//设置迭代器
Iterator it = arr.iterator();
while(it.hasNext()){
Student s = (Student) it.next();
System.out.println(s.name + " " + s.age);
}
}
}
public class Student {
public String name;
public int age;
Student(){
}
Student(String name,int age){
this.name = name;
this.age = age;
}
}
List集合
List集合概述:
- 有序集合,用户可以精准控制列表中每个元素的插入位置
- 用户可以通过整数索引访问元素并搜索列表中的元素
- 与Set集合不同,List允许存在重复的元素
List集合特点:
- 有序:存储和取出的元素顺序一致
- 可重复:存储的元素可以重复
List创建对象
List创建对象同Collection一样,可以引用子类来创建:
//创建对象
List<String> list = new ArrayList<>();
List集合特有方法
方法名 | 说明 |
---|---|
void add(int index,E element) | 在此集合中指定位置插入指定元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
下面给出代码实例:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Demo2 {
public static void main(String[] args) {
//创建对象
List<String> list = new ArrayList<>();
//添加元素:
list.add("Hello");
list.add("World");
//指定位置添加元素:
list.add(0,"yes");
//删除指定索引位置元素:
list.remove(0);
//改变指定位置的元素:
list.set(0,"Nohello");
//返回指定索引处的元素:
System.out.println(list.get(0));
}
}
案例:List集合存储学生对象并遍历
需求:创建一个存储学生对象的集合,存储三个学生对象,使用程序实现在控制台遍历该集合
import java.util.ArrayList;
import java.util.List;
public class application {
public static void main(String[] args) {
//创建对象
List<Student> l = new ArrayList<>();
//创建学生对象
Student s1 = new Student("HOU",20);
Student s2 = new Student("DU",22);
Student s3 = new Student("ZHANG",18);
//加入学生对象
l.add(s1);
l.add(s2);
l.add(s3);
//第一种遍历遍历(for正常遍历):
for (int i = 0; i < l.size(); i++) {
System.out.println(l.get(i).name + " " + l.get(i).age);
}
//第二种遍历(for快捷便利):
for (Student i : l) {
System.out.println(i.name + " " + i.age);
}
//第三种遍历(迭代器遍历):
Iterator it = l.iterator();
while (it.hasNext()){
Student s = (Student) it.next();
System.out.println(s.name + " " + s.age);
}
}
}
特别迭代器ListIterator
ListIterator:列表迭代器
- 通过List集合的listIterator()方法获得,所以说是List集合特有的迭代器
- 允许程序员沿任意方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
- 使用该迭代器时,允许修改list内部的值
ListIterator中常用方法:
- E next():返回迭代中的下一个元素
- boolean hasNext():如果迭代具有更多元素,返回true
- E previous():返回列表中的上一个元素
- boolean hasPrevious():如果此列表迭代器在相反方向遍历列表时具有更多元素,返回true
- void add(E e):将指定元素插入列表
List集合子类(ArraysList和LinkedList)
List集合常用子类:ArrayLIst,LinkedList
- ArrayList:底层数据结构是数组,查询快,增删慢
- LinkedList:底层数据结构是链表,查询慢,增删快
ArrayList集合
ArrayList的底层是数组
ArrayList构造方法
//创建对象
ArrayList<String> array = new ArrayList<>();
ArrayList添加方法
方法名 | 说明 |
---|---|
public boolean add(E e) | 将指定元素追加到集合末尾 |
public void add(int index,E element) | 将指定元素插入到指定位置 |
示例代码:
//添加元素
array.add("hello");
//指定位置添加元素
array.add(0,"before ");
ArrayList集合常用方法
方法名 | 说明 |
---|---|
public boolean remove(Object o) | 删除指定元素,返回是否成功 |
public E remove(int index) | 删除指定位置元素,返回被删除元素 |
public E set(int index,E element) | 修改指定索引处元素,返回被修改元素 |
public E get(int index) | 返回指定索引处的元素 |
public int size() | 返回集合的元素的个数 |
示例代码:
import java.util.ArrayList;
public class Demo1 {
public static void main(String[] args) {
//创建对象
ArrayList<String> array = new ArrayList<>();
//输出对象
System.out.println("array:" + array);
//添加元素
array.add("hello");
array.add("world");
array.add("java");
array.add("111");
System.out.println("array:" + array);
//指定位置添加元素
array.add(0,"before ");
System.out.println("array:" + array);
//删除指定元素:
System.out.println("是否删除成功:" + array.remove("111"));
System.out.println("array:" + array);
//删除指定索引处:
System.out.println("删除的元素是:" + array.remove(0));
System.out.println("array:" + array);
//修改指定索引处:
array.set(0,"Hello");
System.out.println("array:" + array);
//返回索引处:
System.out.println(array.get(0));
//返回元素个数:
System.out.println(array.size());
}
}
案例:存储字符串并遍历
需求:创建一个存储字符串的集合,存储3个字符串元素,使用程序实现在操控台遍历该集合
import java.util.ArrayList;
public class Demo2 {
public static void main(String[] args) {
//创建对象
ArrayList<String> arrays = new ArrayList<>();
//添加元素
arrays.add("HOU");
arrays.add("DU");
arrays.add("ZHANG");
//遍历集合获得并输出:
for (int i = 0; i < arrays.size(); i++) {
System.out.println(arrays.get(i));
}
}
}
案例:存储学生对象并遍历
需求:存储一个存储学生对象的集合,存储三个学生,实用程序实现在控制台遍历该集合
import java.util.ArrayList;
public class application {
public static void main(String[] args) {
//创建ArrayList对象
ArrayList<Student> arr = new ArrayList<Student>();
//创建学生对象
Student s1 = new Student("HOU",20);
Student s2 = new Student("DU",22);
Student s3 = new Student("ZHANG",18);
//加入学生对象
arr.add(s1);
arr.add(s2);
arr.add(s3);
//遍历
for (int i = 0; i < arr.size(); i++) {
System.out.println(arr.get(i).name + " " + arr.get(i).age);
}
}
}
public class Student {
String name;
int age;
Student(){
}
Student(String name,int age){
this.name = name;
this.age = age;
}
}
LinkedList集合特有功能
方法名 | 说明 |
---|---|
public void addFirst(E e) | 在该列表开头插入指定元素 |
public void addLast(E e) | 在该列表末尾插入指定元素 |
public E getFirst() | 返回此列表的第一个元素 |
public E getLast() | 返回此列表的最后一个元素 |
public E removeFirst() | 从此列表删除并返回第一个元素 |
public E removeLast() | 从此列表删除并返回最后一个元素 |
示例代码:
package Demo3;
import java.util.LinkedList;
public class Demo4 {
public static void main(String[] args) {
//创建LinkedList对象
LinkedList<String > linkedList = new LinkedList();
linkedList.addFirst("a");
linkedList.addLast("z");
linkedList.getFirst();
linkedList.getLast();
linkedList.removeFirst();
linkedList.removeLast();
}
}
Set集合
Set集合特点:
- 不包含重复元素的集合
- 没有带索引带方法,所以不能使用普通的for循环遍历
Set集合练习:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Demo {
public static void main(String[] args) {
//创建set对象,以HashSet为对象
Set<String> s = new HashSet<>();
//添加元素(注意,这里没有根据下标添加元素的add方法)
s.add("Hello");
s.add("goodbye");
s.add("java");
//遍历方法(For方法)
for(String i : s){
System.out.println(i);
}
//遍历方法(迭代器方法)
Iterator<String> it = s.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//注意输出结果没有顺序保证
}
}
编译结果:
java
Hello
goodbye
java
Hello
goodbye
HashSet集合概述和特点
HashSet集合特点:
- 底层数据结构是哈希表
- 对集合的迭代顺序不做任何保证,不保证存储和输出的顺序一致
- 没有带索引的方法,不能用普通for循环遍历
- 由于是Set集合,不存在相同元素
下面给出实例展示:
import java.util.HashSet;
public class Demo1 {
public static void main(String[] args) {
//创建对象
HashSet<String > hs = new HashSet<>();
//添加元素
hs.add("Hello");
hs.add("java");
//循环输出
for(String i : hs){
System.out.println(i);
}
}
}
编译结果:
java
Hello
案例:HashSet集合存储学生对象并遍历
需求:创建一个存储学生对象的集合,存储多个学生对象,实用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们认为是同一个变量
import java.util.HashSet;
import java.util.Iterator;
public class appliacation {
public static void main(String[] args) {
//创建HashSet对象
HashSet<Student> hs = new HashSet<>();
//创建学生对象
Student s1 = new Student("HOU",20);
Student s2 = new Student("ZHANG",18);
Student s3 = new Student("DU",19);
Student s4 = new Student("HOU",20);
//添加
hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);
//遍历
Iterator it = hs.iterator();
while (it.hasNext()){
Student s = (Student) it.next();
System.out.println(s.name + " " + s.age);
}
}
}
public class Student {
//学生类
String name;
int age;
public Student(String name,int age){
this.name = name;
this.age = age;
}
//为了比较学生对象成员变量是否相同,我们需要重写hashCOde和equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
编译结果:
DU 19
HOU 20
ZHANG 18
LinkedHashSet集合概述和特点
LinkedHashSet集合特点:
- 哈希表和链表实现的Set接口,具有可预测的迭代次序
- 由于链表保证元素有序,也就是说元素的存储和取出顺序相同
- 由于哈希表保证唯一,所以集合中没有相同元素
下面给出实例展示:
import java.util.LinkedHashSet;
public class Demo1 {
public static void main(String[] args) {
//创建对象
LinkedHashSet<String > lhs = new LinkeHashSet();
//添加元素(重复元素会被删除)
lhs.add("Hello");
lhs.add("java");
lhs.add("java");
//循环输出
for(String i : lhs){
System.out.println(i);
}
}
}
编译结果:
Hello
java
TreeSet集合概述和特点
TreeSet集合特点:
- 元素有序,这里的顺序不是存储和取出的顺序,而是按照一定的规则进行排序,具体排序取决于构造方法
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是set集合,不包含重复元素的集合
TreeSet构造方法:
- TreeSet():根据其元素的自然排序进行排序
- TreeSet(Comparator comparator):根据指定的比较器进行排序
下面给出最简单的实例:
import java.util.TreeSet;
public class Demo1 {
public static void main(String[] args) {
//注意:集合中必须是类,int类型只能采用Integer类
TreeSet<Integer> ts = new TreeSet<>();
//添加数据
ts.add(40);
ts.add(20);
ts.add(20);
ts.add(10);
ts.add(30);
ts.add(50);
//循环遍历
for(int i : ts){
System.out.println(i);
}
}
}
编译结果:
10
20
30
40
50
我们可以看到最后输出按照升序的顺序输出,并且删去了相同元素
自然排序Comparable的使用
案例:存储学生对象并遍历,创建TreeSet集合使用无参构造方法
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
提示:我们可以将类的compareTo方法重写来实现更改Comparable
下面给出示例代码:
import java.util.TreeSet;
public class Demo2 {
public static void main(String[] args) {
//创建TreeSet
TreeSet<Student> ts = new TreeSet<Student>();
//创建对象
Student s1 = new Student("xishi",28);
Student s2 = new Student("diaochan",27);
Student s3 = new Student("yangyuhuan",30);
Student s4 = new Student("wangzhaojun",29);
//创建年龄相同,姓名不同的Student
Student s5 = new Student("xishijiang",28);
//创建年龄相同,姓名相同的Student
Student s6 = new Student("xishijiang",28);
//添加
ts.add(s1);
ts.add(s3);
ts.add(s2);
ts.add(s4);
ts.add(s5);
ts.add(s6);
//For循环
for(Student s : ts){
System.out.println(s.name + " " + s.age);
}
}
}
//这里注意:需要继承Comparable类并且附加<类型>
public class Student implements Comparable<Student>{
String name;
int age;
public Student(String name,int age){
this.name = name;
this.age = age;
}
//对compare方法的重塑
@Override
public int compareTo(Student o) {
//注意return值,return>0正序排列,return<0逆序排列
//return 0;
//先比较年龄
if(this.age > o.age){
return 1;
} else if (this.age < o.age) {
return -1;
}else {
//年龄相同时,比较姓名顺序,因为String存在compare,所以直接调用即可
return this.name.compareTo(o.name);
}
}
}
编译结果:
diaochan 27
xishi 28
xishijiang 28
wangzhaojun 29
yangyuhuan 30
比较器排序Comparator的使用
案例:存储学生对象并遍历,创建TreeSet集合使用有参构造方法
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
提示:我们可以直接在构造中使用匿名内部类来实现比较器的攥写
import java.util.Comparator;
import java.util.TreeSet;
public class Demo3 {
public static void main(String[] args) {
//创建TreeSet并攥写Comparator
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//先比较年龄
if(o1.age > o2.age){
return 1;
} else if (o1.age < o2.age) {
return -1;
}else {
//年龄相同时,比较姓名顺序,因为String存在compare,所以直接调用即可
return o1.name.compareTo(o2.name);
}
}
});
//创建对象
Student s1 = new Student("xishi",28);
Student s2 = new Student("diaochan",27);
Student s3 = new Student("yangyuhuan",30);
Student s4 = new Student("wangzhaojun",29);
//创建年龄相同,姓名不同的Student
Student s5 = new Student("xishijiang",28);
//创建年龄相同,姓名相同的Student
Student s6 = new Student("xishijiang",28);
//添加
ts.add(s1);
ts.add(s3);
ts.add(s2);
ts.add(s4);
ts.add(s5);
ts.add(s6);
//For循环
for(Student s : ts){
System.out.println(s.name + " " + s.age);
}
}
}
public class Student implements Comparable<Student>{
String name;
int age;
public Student(String name,int age){
this.name = name;
this.age = age;
}
}
编译结果:
diaochan 27
xishi 28
xishijiang 28
wangzhaojun 29
yangyuhuan 30
结论:
- 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序
- 比较器排序,就是让集合构造方法接收Comparator的实现类对象,从写compare(T o1,T o2)方法
- 重写方法时,一定注意排列顺序
案例:成绩排序
需求:用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩)并遍历该集合
要求:按照总分从高到低出现
import java.util.TreeSet;
public class application {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<>();
Student s1 = new Student("h",80,90);
Student s2 = new Student("e",90,80);
Student s3 = new Student("r",100,90);
ts.add(s1);
ts.add(s2);
ts.add(s3);
for(Student s : ts){
System.out.println(s.name);
}
}
}
public class Student implements Comparable<Student>{
//基本信息
String name;
int chinese;
int math;
int sum;
//构造:
Student(String name,int chinese,int math){
this.name = name;
this.chinese = chinese;
this.math = math;
this.sum = chinese+math;
}
//对compare方法的重塑
public int compareTo(Student o) {
//注意return值,return>0正序排列,return<0逆序排列
//return 0;
//先比较年龄
if(this.sum > o.sum){
return -1;
} else if (this.sum < o.sum) {
return 1;
}else {
//年龄相同时,比较姓名顺序,因为String存在compare,所以直接调用即可
return this.name.compareTo(o.name);
}
}
}
编译结果:
r
e
h
案例:不重复的随机数
需求:编写一个程序,获取10个1~20之间的随机数,要求随机数不能重复,并在控制台输出
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class Demo4 {
public static void main(String[] args) {
//创建set
Set<Integer> s = new HashSet<>();
//创建随机数对象
Random r = new Random();
//判断是否10个
while (s.size() < 10){
//创建随机数并加入集合
int a = r.nextInt(20)+1;
s.add(a);
}
for (int i : s){
System.out.println(i);
}
}
}
编译结果:
//10个不同的数
16
17
18
5
6
7
8
9
11
15
Map集合
Map集合概述:
- interface Map<K,V> K:键的类型 V:值的类型
- 将键映射到值的对象;不能包含重复的键;每个键可以映射到最多一个值
- 举例:学生的学号和姓名
创造Map集合的对象:
- 多态的方式
- 具体的实现类HashMap
构造方法:
Map<String,String > map = new HashMap<String,String>();
Map集合基本功能
下面给出方法表格:
方法名 | 说明 |
---|---|
V put(K key,V value) | 增加元素 |
V remove(Object key) | 根据键删除键值对应的元素 |
void clear() | 移除所有的键值对元素 |
boolean containsKey(Object key) | 判断是否包含指定键 |
boolean containsValue(Object value) | 判断是否包含指定值 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度 |
下面给出方法实例:
import java.util.HashMap;
import java.util.Map;
public class Demo2 {
public static void main(String[] args) {
//创建对象
Map<String,String > map = new HashMap<String,String>();
//添加元素:
map.put("001","HOU");
map.put("002","ZHANG");
map.put("003","DU");
//打印检测:
System.out.println(map);
//删除元素:
map.remove("002");
//打印检测:
System.out.println(map);
//全部清空:
map.clear();
//打印检测:
System.out.println(map);
//重新输入:
map.put("001","HOU");
map.put("002","ZHANG");
map.put("003","DU");
//判断是否包含指定键
System.out.println(map.containsKey("001"));
//判断是否包含指定值
System.out.println(map.containsValue("ZHANG"));
//判断是否为空
System.out.println(map.isEmpty());
//集合长度反馈
System.out.println(map.size());
}
}
编译结果:
{001=HOU, 002=ZHANG, 003=DU}
{001=HOU, 003=DU}
{}
true
true
false
3
Map集合获取功能
下面给出方法表格:
方法名 | 说明 |
---|---|
V get(Object key) | 根据键获得值 |
Set |
获得所有键的集合 |
Collection |
获得所有值的集合 |
Set<Map.Entry<K,V>>entrySet() | 获得所有键值对对象的集合 |
下面给出方法实例:
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo3 {
public static void main(String[] args) {
//创建对象
Map<String,String > map = new HashMap<String,String>();
//添加元素:
map.put("001","HOU");
map.put("002","ZHANG");
map.put("003","DU");
//获得键->值
System.out.println(map.get("001"));
//获得所有键的集合:(用Set获得Map的所有Key集合)
Set<String> sets = map.keySet();
for(String s : sets){
System.out.println(s);
}
//获得所有值的集合:(用Collection获得Map的所有Value集合)
Collection<String > collections = map.values();
for(String i : collections){
System.out.println(i);
}
//获取键值对(用Set获取类型为Map.Entry<String,String>的类型集合)
Set<Map.Entry<String,String >> entrySet = map.entrySet();
for (Map.Entry<String,String> m : entrySet){
System.out.println(m.getKey() + ":" + m.getValue());
}
}
}
编译结果:
HOU
001
002
003
HOU
ZHANG
DU
001:HOU
002:ZHANG
003:DU
Map集合遍历
下面我将给出两种遍历方法:
- 先获得所有键的集合,再根据键输出值
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo4 {
public static void main(String[] args) {
//创建对象
Map<String,String > map = new HashMap<String,String>();
//添加元素:
map.put("001","HOU");
map.put("002","ZHANG");
map.put("003","DU");
//1.首先获得所有键:
Set<String > sets = map.keySet();
//遍历到所有键:
for(String s : sets){
//针对所有键取到值:
System.out.println(s + ":" + map.get(s));
}
}
}
- 获得键值对对象的集合,根据集合的getKey()和getValue()获得键和值
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo5 {
public static void main(String[] args) {
//创建对象
Map<String,String > map = new HashMap<String,String>();
//添加元素:
map.put("001","HOU");
map.put("002","ZHANG");
map.put("003","DU");
//1.首先获取键值对
Set<Map.Entry<String,String >> entrySet = map.entrySet();
//遍历并输出:
for (Map.Entry<String,String> m : entrySet){
System.out.println(m.getKey() + ":" + m.getValue());
}
}
}
案例:HashMap集合存储学生对象并遍历(1)
需求:创建一个HashMap集合,键是学号,值是学生对象;存储三个键值对并遍历
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo1 {
public static void main(String[] args) {
//创建map对象
Map<String,Demo2> map = new HashMap<String,Demo2>();
//创建学生对象
Demo2 s1 = new Demo2("HOU",20);
Demo2 s2 = new Demo2("DU",22);
Demo2 s3 = new Demo2("ZHANG",18);
//加入学生对象
map.put("001",s1);
map.put("002",s2);
map.put("003",s3);
//遍历:
Set<String> sets = map.keySet();
for(String s : sets){
System.out.println(s + ":" + map.get(s).name + " " + map.get(s).age);
}
}
}
public class Demo2 {
public String name;
public int age;
Demo2(){
}
public Demo2(String name, int age){
this.name = name;
this.age = age;
}
}
编译结果:
001:HOU 20
002:DU 22
003:ZHANG 18
案例:HashMap集合存储学生对象并遍历(2)
需求:创建一个HashMap集合,键是学生对象,值是居住地,存储多个键值对元素并遍历
注意:要保证键的唯一性:如果学生对象的成员变量相同,认为是同一个对象
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo1 {
public static void main(String[] args) {
//创建对象
Map<Demo2,String> map = new HashMap<Demo2,String>();
//创建学生对象
Demo2 s1 = new Demo2("HOU",20);
Demo2 s2 = new Demo2("DU",22);
Demo2 s3 = new Demo2("ZHANG",18);
Demo2 s4 = new Demo2("ZHANG",18);
//加入学生对象
map.put(s1,"北京");
map.put(s2,"上海");
map.put(s3,"成都");
map.put(s3,"西安");
//遍历:
Set<Map.Entry<Demo2,String>> sets = map.entrySet();
for(Map.Entry<Demo2,String> m : sets){
System.out.println(m.getKey().name + " " + m.getKey().age + " " + m.getValue());
}
}
}
public class Demo2 {
public String name;
public int age;
Demo2(){
}
Demo2(String name,int age){
this.name = name;
this.age = age;
}
//需要重写equals和hashCode
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Demo2 demo2 = (Demo2) o;
if (age != demo2.age) return false;
return name != null ? name.equals(demo2.name) : demo2.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
编译结果:
DU 22 上海
HOU 20 北京
ZHANG 18 西安
案例:ArrayList集合存储HashMap元素并遍历
需求:创建一个ArrayList集合,存储三个元素,每个元素都是HashMap,每个HashMap的键都是String,并遍历
import java.util.*;
public class Demo1 {
public static void main(String[] args) {
//创建ArraysList集合
ArrayList<HashMap<String,String>> arr = new ArrayList<>();
//创建Map对象
HashMap<String,String> hm1 = new HashMap<>();
hm1.put("大乔","孙策");
hm1.put("小乔","周瑜");
HashMap<String,String> hm2 = new HashMap<>();
hm2.put("北京","上海");
hm2.put("河南","河北");
HashMap<String,String> hm3 = new HashMap<>();
hm3.put("小说","漫画");
hm3.put("游戏","学习");
//添加:
arr.add(hm1);
arr.add(hm2);
arr.add(hm3);
//遍历:
for (int i = 0; i < arr.size(); i++) {
System.out.println("第" + (i+1) + "个Map:");
Set<Map.Entry<String,String>> sets = arr.get(i).entrySet();
for(Map.Entry<String,String> m : sets){
System.out.println(m.getKey() + ":" + m.getValue());
}
}
}
}
编译结果:
第1个Map:
大乔:孙策
小乔:周瑜
第2个Map:
河南:河北
北京:上海
第3个Map:
游戏:学习
小说:漫画
案例:HashMap集合存储ArrayList元素并遍历
需求:创建一个HashMap集合,存储三个键值对元素,每个键值对元素的键都是String,每个键值对元素的值都是ArrayList,每个ArrayList的值都是String,并遍历
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
public class Demo2 {
public static void main(String[] args) {
//创建Map集合
HashMap<String, ArrayList<String>> hm = new HashMap<>();
//创建ArrayList
ArrayList<String> al1 = new ArrayList<>();
al1.add("水浒传");
al1.add("西游记");
ArrayList<String> al2 = new ArrayList<>();
al2.add("周瑜");
al2.add("小乔");
ArrayList<String> al3 = new ArrayList<>();
al3.add("齐天大圣");
al3.add("紫霞仙子");
//添加:
hm.put("001",al1);
hm.put("002",al2);
hm.put("003",al3);
//遍历:
Set<String> sets = hm.keySet();
for(String s : sets){
System.out.println(s);
for(String ss : hm.get(s)){
System.out.println(ss);
}
}
}
}
编译结果:
001
水浒传
西游记
002
周瑜
小乔
003
齐天大圣
紫霞仙子
案例:统计字符串中每个字符出现的次数
需求:键盘录入一个字符串,要求统计字符串中每个字符出现的次数
要求:结果如a(5)b(4)c(2)这样输出
import java.util.HashMap;
import java.util.Scanner;
import java.util.Set;
public class Demo1 {
public static void main(String[] args) {
//键盘录入字符串
Scanner scanner = new Scanner(System.in);
System.out.println("请输入字符串:");
String chars = scanner.nextLine();
//创建Map来判断
HashMap<Character, Integer> map = new HashMap<>();
//判断输入是否为空
if(chars.isEmpty()){
System.exit(0);
}
//循环判断
for(int i=0;i < chars.length();i++){
char test = chars.charAt(i);
if(!map.containsKey(test)){
map.put(test, 1);//如果没有,就添加
}else {
//如果有,就把value++,再写进去
int j = (int) map.get(test);
j++;
map.remove(test);
map.put(test,j);
}
}
//循环出所有的集合键值:
Set<Character> sets = map.keySet();
for(char c : sets){
System.out.println(c + "(" + map.get(c) + ")");
}
}
}
编译结果:
请输入字符串:
aaaabbcccdf
a(4)
b(2)
c(3)
d(1)
f(1)
Collections类
Collection类的概述:
- 针对集合操作的工具
Collections类的方法:
方法名 | 说明 |
---|---|
Collections.sort(List |
将指定列表按升序排列 |
Collections.reverse(List |
反转指定列表中的元素 |
Collections.shuffle(List |
使用默认的随机源随机排列指定的元素 |
下面给出方法实例:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ClassCollections {
public static void main(String[] args) {
//创建一个测试List
List<Integer> l = new ArrayList<>();
l.add(20);
l.add(30);
l.add(50);
l.add(40);
System.out.println(l);
//排序方法
Collections.sort(l);
System.out.println(l);
//反转方法
Collections.reverse(l);
System.out.println(l);
//随机置换方法:
Collections.shuffle(l);
System.out.println(l);
}
}
编译结果:
[20, 30, 50, 40]
[20, 30, 40, 50]
[50, 40, 30, 20]
[50, 40, 30, 20]
案例:ArrayList存储学生对象并排序
需求:ArrayList存储学生对象,使用Collections对ArrayList进行排序‘
要求:按年龄从小到大排序,年龄相同时,按照姓名字母顺序排列
import Map.test1.Demo2;
import java.util.*;
public class Demo1 {
public static void main(String[] args) {
//创建ArrayList对象
ArrayList<Demo2> arr = new ArrayList<>();
//创建学生对象
Demo2 s1 = new Demo2("HOU",20);
Demo2 s2 = new Demo2("DU",22);
Demo2 s3 = new Demo2("ZHANG",18);
//加入学生对象
arr.add(s1);
arr.add(s2);
arr.add(s3);
//采用Collections类,通过重写comparator来完成
Collections.sort(arr, new Comparator<Demo2>() {
@Override
public int compare(Demo2 o1, Demo2 o2) {
int i = o1.age-o2.age;
if(i != 0){
return i;
}else {
return o1.name.compareTo(o2.name);
}
}
});
for(Demo2 d : arr){
System.out.println(d.name + " " + d.age);
}
}
}
public class Demo2 {
public String name;
public int age;
Demo2(){
}
Demo2(String name,int age){
this.name = name;
this.age = age;
}
}
编译结果:
ZHANG 18
HOU 20
DU 22
总结案例:模拟斗地主
下面我们给出模拟斗地主的两种模式,以便于你总结前面学的东西;
模拟斗地主(1)
需求:通过程序实现斗地主过程中的洗牌,发牌,看牌
思路:
- 创建一个牌盒,定义一个集合对象,这里采用ArrayList集合实现
- 往牌盒里面装牌
- 洗牌,采用Collections的shuffle方法实现
- 发牌,遍历集合给三个玩家发牌,并保留地主牌
- 看牌,三个玩家分别遍历自己的牌
代码如下:
import java.util.ArrayList;
import java.util.Collections;
public class Demo1 {
public static void main(String[] args) {
//创建牌盒ArrayList
ArrayList<String > array = new ArrayList<>();
//往牌盒里装牌:
/*
* 花色:♠,♥,♣,♦
* 大小:2,3,4,5,6,7,8,9,10,J,Q,K,A
* 大王,小王
*/
//定义花色数组
String[] color = {"♠","♥","♣","♦"};
//定义大小数组
String[] number ={"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
//拼接并装入:
for (String c : color){
for(String n : number){
String s = c + n;
array.add(s);
}
}
array.add("大王");
array.add("小王");
//洗牌:
Collections.shuffle(array);
//发牌(需要有三个玩家,创建三个集合ArrayList,创造一个地主集合,有三张地主牌,)
ArrayList<String > play1 = new ArrayList<>();
ArrayList<String > play2 = new ArrayList<>();
ArrayList<String > play3 = new ArrayList<>();
ArrayList<String > land = new ArrayList<>();
for(int i=0;i < array.size();i++){
//最后三张地主牌
if(i > array.size()-4){
land.add(array.get(i));
continue;
}
//一号玩家先拿,二号玩家第二拿,三号玩家最后拿
if(i%3 == 0){
play1.add(array.get(i));
} else if (i%3 == 1) {
play2.add(array.get(i));
}else {
play3.add(array.get(i));
}
}
//看牌方法一样,我们通过方法来写
lookPoker("play1",play1);
lookPoker("play2",play2);
lookPoker("play3",play3);
lookPoker("底牌",land);
}
public static void lookPoker(String name,ArrayList<String> arr){
System.out.print(name + "的牌是:");
for(String s : arr){
System.out.print(s + " ");
}
System.out.println();
}
}
编译结果;
play1的牌是:♦10 ♣J ♠8 ♥6 ♣Q ♣7 ♠5 ♦4 ♥3 ♦J ♠4 ♦3 ♦2 ♣9 ♥5 小王 ♦8
play2的牌是:♥2 ♠2 ♠J ♠Q ♦7 ♥7 ♥J ♣3 ♠6 ♣4 ♦A ♣A ♥10 ♥4 ♠10 ♣8 ♣5
play3的牌是:♣6 ♠9 ♠A ♦6 大王 ♠7 ♥K ♣10 ♥8 ♥A ♦5 ♣2 ♦Q ♦K ♥9 ♥Q ♦9
底牌的牌是:♣K ♠K ♠3
模拟斗地主(2)
需求:通过程序实现斗地主过程中的洗牌,发牌,看牌
要求:对牌排序
思维导图:
思路:
- 创建HashMap,键是编号,值是牌
- 创建ArrayList,存储编号
- 创建花色数组和点数数组
- 从0开始往HashMap里面存储序号并存储对应牌;同时往ArrayList里面存储编号
- 洗牌,同样使用Collections中的shuffle方法
- 发牌,(发的是ArrayList中的编号,为了保证编号排序,这里采用TreeSet集合接收)
- 定义方法看牌(遍历TreeSet集合,获得编号,通过HashMap集合找到对应的牌)
- 调用看牌方法
代码如下:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;
public class Demo2 {
public static void main(String[] args) {
//创造对应Map
HashMap<Integer, String> hashmap = new HashMap<>();
//创造ArrayList
ArrayList<Integer> array = new ArrayList<>();
//创建花色数组和大小数组
String[] color = {"♠","♥","♣","♦"};
String[] number ={"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
//写入Map
int ii=0;
for (String n : number){
for(String c : color){
String s = c + n;
array.add(ii);
hashmap.put(ii,s);
ii++;
}
}
hashmap.put(52,"小王");
hashmap.put(53,"大王");
array.add(52);
array.add(53);
//洗牌:
Collections.shuffle(array);
//发牌:
//发牌(需要有三个玩家,创建三个集合ArrayList,创造一个地主集合,有三张地主牌,)
TreeSet<Integer> play1 = new TreeSet();
TreeSet<Integer> play2 = new TreeSet();
TreeSet<Integer> play3 = new TreeSet();
TreeSet<Integer> land = new TreeSet();
for(int i=0;i < array.size();i++){
//最后三张地主牌
if(i > array.size()-4){
land.add(array.get(i));
continue;
}
//一号玩家先拿,二号玩家第二拿,三号玩家最后拿
if(i%3 == 0){
play1.add(array.get(i));
} else if (i%3 == 1) {
play2.add(array.get(i));
}else {
play3.add(array.get(i));
}
}
//看牌方法一样,我们通过方法来写
lookPoker("play1",play1,hashmap);
lookPoker("play2",play2,hashmap);
lookPoker("play3",play3,hashmap);
lookPoker("底牌",land,hashmap);
}
public static void lookPoker(String name,TreeSet<Integer> array,HashMap<Integer, String> hashmap){
System.out.print(name + "的牌是:");
for(int i : array){
System.out.print(hashmap.get(i));
}
System.out.println();
}
}
编译结果:
play1的牌是:♣2♦2♥3♣4♦4♦6♦7♠8♣8♦8♠9♠10♦10♠A♥A♣A♦A
play2的牌是:♣5♠6♥6♣7♣9♦9♣10♥J♣J♦J♥Q♣Q♦Q♠K♥K♣K小王
play3的牌是:♠2♥2♠3♣3♦3♠4♠5♥5♦5♣6♠7♥8♥9♥10♠J♠Q大王
底牌的牌是:♥4♥7♦K
结束语
好的,关于集合的话题我们就讲到这里了