Java 学习笔记·九 —— Java 常用工具·集合

Java 常用工具

集合

集合,即集,是用来存储多个元素的容器

集合与数组的区别
  • 元素类型:
    集合:引用类型(存储基本类型时自动装箱)
    数组:基本类型、引用类型
  • 元素个数:
    集合:不固定,可任意扩容
    数组:固定,不能改变容量
集合的好处

不受容器大小限制,可以随时添加、删除元素
提供了大量操作元素的方法(判断、获取等)

Java 的集合体系

单列集合(Collection

ListArrayList

SetHashSet

双列集合(Map: key, value

MapHashMap

List 集合的特点与应用

特点:

可重复、有序(存取顺序相同)

应用:

List list = new ArrayList();

List 接口的成员方法:

  • public boolean add(E e)
    添加元素到集合的末尾, E 是泛型的意思

  • public E get(int index)
    根据索引,搜索对应的元素

  • public int size()
    获取集合的长度

List 是接口,可通过创建其子类 ArrayList 对象来完成该接口的实例化
List list = new ArrayList();

代码:

package cn.itcast.demo1;
import java.util.Objects;

//学生类
public class Student {
    //成员变量
    private String name;
    private int age;
    public Student() {
    }
    public Student(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 "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package cn.itcast.demo1;

import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        //需求: 往List集合中添加3个学生对象, 然后遍历.
        //1. 创建集合对象.
        List list = new ArrayList();
        //2. 创建元素对象.
        Student s1 = new Student("乔峰",41);
        Student s2 = new Student("乔峰",41);
        Student s3 = new Student("虚竹",38);
        Student s4 = new Student("段誉",26);
        //3. 将元素对象添加到集合对象中.
        /*boolean b1 = list.add(s1);
        System.out.println(b1);
        boolean b2 = list.add(s1);
        System.out.println(b2);*/
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);

        //直接打印集合
        System.out.println(list);
        //获取索引为2的元素
        Object obj = list.get(2);
        System.out.println("索引为2的元素是: " + obj);
        //获取集合中的元素个数
        System.out.println("集合的长度为: " + list.size());
        System.out.println("-------------------");

        //4. 遍历集合.
        for (int i = 0; i < list.size(); i++) {
            //i表示的就是集合中每个元素的索引
            //获取元素
            Object obj2 = list.get(i);
            System.out.println("索引为 " + i + "的元素是: " + obj2 );
        }
    }
}
增强 for 循环和迭代器
增强 for 循环

增强 for 循环可以简化数组和集合的遍历,是迭代器的简写形式

格式:

for (数据类型 变量名:数组或者集合对象) {
	// 循环体,变量即元素
}
package cn.itcast.demo2;

import java.util.ArrayList;
import java.util.List;

 */
public class Test {
    public static void main(String[] args) {
        //需求: 通过增强for遍历List集合.
        //1. 创建集合对象.
        List list = new ArrayList();
        //2. 创建元素对象.
        //3. 将元素对象添加到集合对象中.
        list.add(10);
        list.add(10);
        list.add(30);
        list.add(20);
        list.add(40);

        //4. 遍历集合.
        for(Object obj : list) {
            //obj是集合中的元素, 其本身应该是Integer类型的数据.
            Integer ii = (Integer)obj;
            System.out.println(ii);
        }
        System.out.println("-------------------");

        for (Object obj : list) {
            Integer ii = (Integer)obj;
            System.out.println(ii);
        }
    }
}

IDEA 快捷键:iter + 回车

迭代器

对过程的迭代,称为迭代

迭代器是遍历 Collection 集合的通用方式,可以对集合进行遍历

列表迭代器是 List 体系独有的遍历方式, 可以在对集合遍历的同时进行添加、删除等操作。
但是必须通过调用列表迭代器的方法来实现.

常用方法:

  • next()
    返回迭代的下一个元素对象
  • hasNext()
    如果仍有元素可以迭代,则返回 true

用法:
根据集合对象,获取其对象的迭代器对象

案例:

package cn.itcast.demo2;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class CollectionDemo {
    public static void main(String[] args) {
        // 迭代器
        List list2 = new ArrayList();
        list2.add("a");
        list2.add("b");
        list2.add("c");
/*        Iterator it = list2.iterator();
        // 判断迭代器中是否有元素
        while(it.hasNext()) { 
        // 如果有元素,就一直迭代(遍历)
            // 如果有就获取元素
            String s = (String)it.next();
            if ("b".equals(s)) {
                // 常量与变量的比较,一般把常量写在前面
                // 可以规避 空指针异常
                // 下面的操作会报异常(并发修改异常)
                // ConcurrentModificationException

                list2.add("Java");
            }
            System.out.println(i);
        }*/

		// 列表迭代器
        ListIterator lit = list2.listIterator();
        while(lit.hasNext()) { // 如果有元素,就一直迭代(遍历)
            // 如果有就获取元素
            String s = (String)lit.next();
            if ("b".equals(s)) {
                // 常量与变量的比较,一般把常量写在前面
                // 可以规避 空指针异常
                lit.add("Java");
            }
            System.out.println(s);
        }
        System.out.println("---------");
        System.out.println(list2);
    }
}

总结:
普通的迭代器(Iterator)在遍历集合的同时不能添加或者删除元素, 否则会报: 并发修改异常 (ConcurrentModificationException
列表迭代器(ListIterator)在遍历集合的同时可以修改集合中的元素(添加, 删除等),必须使用列表迭代器中的方法.

泛型

泛型,即泛指任意类型,又叫参数化类型(Parameterized Type),对具体类型的使用起到辅助作用,类似于方法的参数

集合类泛型:表示该集合中存放指定类型的元素

示例:

// 给 List 集合加上泛型 Student
List<Student> list = new ArrayList<>();

泛型,可以保证类型安全,避免了类型转换

package cn.itcast.demo4;

import java.util.ArrayList;
import java.util.List;

/*
    泛型一般只和集合类相结合使用.
    泛型是JDK5的新特性, 但是从JDK7开始,后边的泛型可以不用写具体的数据类型了(菱形泛型.)
 */
public class Test {
    public static void main(String[] args) {
        //不使用泛型的集合
        //1. 创建集合对象.
        List list1 = new ArrayList();
        //2. 创建元素对象.
        //3. 将元素对象添加到集合对象中
        list1.add("a");
        list1.add("b");
        list1.add("c");
        //list1.add(10);  会报类型转换异常(ClassCastException)

        //4. 遍历集合.
        for (Object obj : list1) {
            String s = (String)obj;
            System.out.println(s);
        }
        System.out.println("----------------");

        //需求: 演示泛型
        //1. 创建集合对象.
       List<String> list2 = new ArrayList<>();
        //2. 创建元素对象.
        //3. 将元素对象添加到集合对象中
        list2.add("abc");
        list2.add("bcd");
        list2.add("cde");

        //4. 遍历集合.
        for (String s : list2) {
            System.out.println(s);
        }
    }
}

Colletions 工具类

Collections 工具类,是针对集合进行操作的工具类

成员方法
  • sort(List<T>, Comparator<T>)
    根据比较器规则对列表进行排序

  • max(Collection<T>)
    返回集合的最大元素

  • reverse(List<T>)
    反转 List 集合元素

  • shuffle(List<T>)
    使用默认的随机源随机置换指定的列表

package cn.itcast.demo5;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        //创建集合对象.
        List<Integer> list = new ArrayList<>();
        //往集合中添加数据
        list.add(1);
        list.add(3);
        list.add(3);
        list.add(5);
        list.add(2);
        list.add(2);
        list.add(4);

        //打印集合
        System.out.println("没有操作以前, 集合中的数据是: " + list);
        System.out.println("-------------------------");

        //获取集合中最大元素
        Integer max = Collections.max(list);
        System.out.println("集合中的最大元素为: " + max);
        System.out.println("-------------------------");

        //对集合进行升序排列
        /*Collections.sort(list);
        System.out.println("升序排列后的结果为: " + list);
        System.out.println("-------------------------");*/

        //对集合中的数据进行反转.
        /*Collections.reverse(list);
        System.out.println("反转以后集合中的数据为: " + list);*/

        //需求: 对集合中的数据进行降序排列
        //先对集合中的数据进行: 升序排列
        /*Collections.sort(list);
        //然后反转集合中的数据.
        Collections.reverse(list);
        System.out.println("降序后的结果为: " + list);*/
        System.out.println("-------------------------");

        //随机置换, 相当于洗牌
        Collections.shuffle(list);
        System.out.println("随机置换后的结果为: " + list);
    }
}

Set 集合的特点与应用

特点:

不可重复(唯一)、无序(元素的存取顺序不一致)

应用:

Set<T> set = new HashSet<>();

向集合中添加元素的方法为:add()

遍历集合的方式:迭代器

获取集合中元素个数的方法:size()

package cn.itcast.demo6;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        //需求: 往set集合中添加5个学生对象, 然后遍历.
        //1. 创建集合对象.
        Set<Student> set = new HashSet<>();
        //2. 创建元素对象.
        Student s1 = new Student("乔峰", 41);
        Student s2 = new Student("虚竹", 38);
        Student s3 = new Student("段誉", 26);
        Student s4 = new Student("乔峰", 41);
        Student s5 = new Student("虚竹", 38);

        //3. 将集合对象添加到元素对象中.
        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);
        set.add(s5);

        //4. 遍历集合.
        System.out.println(set);
        System.out.println("-------------------------");

        System.out.println("通过迭代器实现");
        //通过迭代器遍历Set集合
        //A. 通过集合对象获取其对应的迭代器对象.
        Iterator<Student> it = set.iterator();
        //B. 判断迭代器中是否有元素.
        while(it.hasNext()) {
            //C. 如果有, 就获取元素.
            Student s = it.next();
            System.out.println(s);
        }
        System.out.println("-------------------------");

        //通过增强for遍历Set集合
        System.out.println("通过增强for遍历Set集合");
        for (Student student : set) {
            System.out.println(student);
        }
    }
}

但是如果是自定义类型,set 中可能出现”重复元素“

为什么 Set 集合中没有”去重“?

因为,Set 集合保证元素的唯一性,依赖于:equals()hashCode() 两个方法;
如果在自定义类中,没有重写这两个方法,默认调用的是 Object 类中的这两个方法,Object 类中的 equals() 方法默认比较的是 地址值是否相同

解决方法:

重写这两个方法

package cn.itcast.demo6;

import java.util.Objects;

//学生类
public class Student {
    //成员变量
    private String name;
    private int age;
    public Student() {
    }
    public Student(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 "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

Map 集合的特点

特点:

双列集合,元素由键值对(Entry)构成:key -- value
key : 不可以重复
value : 可以重复

应用:

Map<T1, T2> map = new HashMap<>();

T1: 表示键的数据类型.
T2: 表示值的数据类型

成员方法:
put(K key,V value);
添加元素(键值对的形式);
元素第一次添加,返回 null
重复添加,会用新值覆盖旧值,并返回旧值.

get(Object key);
根据键获取其对应的值

Set<K> keySet();
获取所有键的集合.

遍历集合的方式:

  1. 获取所有的 keykeySet()
  2. 遍历 keySet,通过 key 获取 valueget()

遍历 keySet 的方法:iterator()

package cn.itcast.demo1;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        //需求: 往Map集合中添加3个学生对象, 然后打印.
        //1. 创建集合对象.
        //键: 学生的编号,  值: 具体的学生对象
        Map<Integer,Student> map = new HashMap<>();
        //2. 创建元素对象.
        Student s1 = new Student("张三", 23);
        Student s2 = new Student("李四", 24);
        Student s3 = new Student("张三", 23);

        //3. 将元素对象添加到集合中.
        /*Student stu1 = map.put(1, s1);
        System.out.println("stu1: " + stu1);
        Student stu2 = map.put(1, s2);
        System.out.println("stu2: " + stu2);*/
        map.put(1, s1);
        map.put(2, s2);
        map.put(3, s3);

        //根据键,获取值
        Student stu3 = map.get(3);
        System.out.println("key: " + 2 + ", value:" + stu3);

        //打印集合
        System.out.println(map);
        System.out.println("----------------------------");

        //4. 遍历集合.
      /*  //4.1. 获取所有键的集合.                 keySet()
        Set<Integer> keys = map.keySet();
        //4.2. 遍历所有的键, 获取到每一个键.     迭代器, 增强for.
        //获取迭代器对象
        Iterator<Integer> it = keys.iterator();
        while(it.hasNext()) {
            //如果迭代器中有数据, 就获取.
            Integer key = it.next();
            //4.3. 根据键, 获取指定的值.             get()
            Student value = map.get(key);
            System.out.println("key: " + key + "...value:" + value);
        }*/

        //通过增强for实现
        //获取到所有的键
        Set<Integer> keys = map.keySet();
        for (Integer key : keys) {
            //key就是双列集合中的每一个键.
            Student value = map.get(key);
            System.out.println(key + "..." + value);
        }
    }
}

案例

package cn.itcast.demo2;

import java.util.*;

/*
    需求: 模拟斗地主发牌
        步骤:
            1. 买牌.
            2. 洗牌.
            3. 发牌.
            4. 看牌.
 */
public class SendPokerTest {
    public static void main(String[] args) {
        //1. 买牌.
        //1.1 定义一个双列集合, 键: 表示牌的编号, 值: 表示具体的牌.  规则: 编号越小, 牌越小.
        Map<Integer, String> pokers = new HashMap<>();
        //1.2 定义一个单列集合, 用来存储所有牌的编号.
        List<Integer> list = new ArrayList<>();
        //1.3 具体的买牌动作.
        //普通牌, 52.
        String[] colors = {"♠","♥","♣","♦"};
        String[] numbers = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
        int num = 0;    //表示牌的编号.
        //通过循环嵌套, 造 普通牌
        for (String number : numbers) {     //外循环, 获取所有的点数
            for (String color : colors) {   //内循环, 获取所有的花色
                String poker = color + number;
                //将牌的编号, 具体的牌放到双列集合中.
                pokers.put(num, poker);
                //将牌的编号放到单列集合中.
                list.add(num);
                //每添加一张牌, 编号要自增1.
                num++;
            }
        }
        //大小王.
        //添加小王
        pokers.put(num, "小王");
        list.add(num++);

        //添加大王
        pokers.put(num, "大王");
        list.add(num);

        //打印牌就可以了.
        System.out.println("所有的牌: " + pokers);
        System.out.println("牌的编号:" + list);

        //2. 洗牌
        Collections.shuffle(list);
        System.out.println("洗好牌后, 编号为: " + list);

        //3. 发牌.
        //3.1 定义4个集合, 分别表示3个玩家, 底牌.
        List<Integer> liuyifei = new ArrayList<>();
        List<Integer> zhaoliying = new ArrayList<>();
        List<Integer> xiaohei = new ArrayList<>();
        List<Integer> dipai = new ArrayList<>();

        //3.2 具体的发牌动作, 将索引和3取模, 决定发给谁.
        for (int i = 0; i < list.size(); i++) {
            //获取编号
            Integer pokerNum = list.get(i);
            //System.out.println(pokerNum);
            if (i >= list.size() - 3) {
                //底牌
                dipai.add(pokerNum);
            } else if(i % 3 == 0) {
                liuyifei.add(pokerNum);
            } else if(i % 3 == 1) {
                zhaoliying.add(pokerNum);
            } else if(i % 3 == 2) {
                xiaohei.add(pokerNum);
            }
        }
        /*//3.3 查看玩家, 底牌的编号.
        System.out.println("liuyifei: " + liuyifei);
        System.out.println("zhaoliying: " + zhaoliying);
        System.out.println("xiaohei: " + xiaohei);
        System.out.println("dipai: " + dipai);*/

        //4. 查看具体的牌
        System.out.println("----------------------------------");
        /*String str = printPoker(liuyifei, pokers);
        System.out.println("liuyifei: " + str);*/

        System.out.println("liuyifei: " + printPoker(liuyifei, pokers));
        System.out.println("zhaoliying: " + printPoker(zhaoliying, pokers));
        System.out.println("xiaohei: " + printPoker(xiaohei, pokers));
        System.out.println("dipai: " + printPoker(dipai, pokers));

    }

    /*
        4. 定义一个方法, 用来看牌
            方法名:   printPoker
            参数列表: List<Integer>, Map<Integer, String>
            返回值:  String
     */
    public static String printPoker(List<Integer> nums, Map<Integer,String> pokers) {
        //1. 对牌的编号进行升序排列.
        Collections.sort(nums);
        //2. 遍历牌的编号集合, 获取到每一个编号.
        StringBuilder sb = new StringBuilder();
        for (Integer num : nums) {
            //num就是要查找的具体牌的 编号.
            //3. 根据编号去双列集合中查找该编号对应的具体牌.
            String poker = pokers.get(num);
            //4. 将获取到的牌进行拼接.
            sb.append(poker + " ");
        }
        //5. 将最后拼接结果返回即可.
        String str = sb.toString();
        return str.trim();
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值