Java集合详解

Java集合详解

集合类的特点:

  • 提供一种存储空间可变的存储模型,存储的数据容量可以发生改变

集合类的整体构造模式:

集合类名<类型> 集合对象名 = new 集合类名<类型>();

集合类体系结构:

  1. 集合
    1. Collection(单列)
      1. List(可重复)
        1. ArrayList
        2. LinkedList
      2. Set(不可重复)
        1. HashSet
        2. TreeSet
    2. Map(双列)
      1. HashMap

增强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 KeySet() 获得所有键的集合
Collection values() 获得所有值的集合
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集合遍历

下面我将给出两种遍历方法:

  1. 先获得所有键的集合,再根据键输出值
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));
        }
    }
}
  1. 获得键值对对象的集合,根据集合的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 list) 将指定列表按升序排列
Collections.reverse(List list) 反转指定列表中的元素
Collections.shuffle(List 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

结束语

好的,关于集合的话题我们就讲到这里了

posted @ 2022-07-06 15:28  秋落雨微凉  阅读(47)  评论(0编辑  收藏  举报