7---可变参数+Collections集合工具类+冒泡排序+Map集合

本文深入讲解了Java集合框架中的各种核心概念,包括可变参数、Collection接口及其常用方法、Comparator接口的使用、冒泡排序算法、Map接口及其实现类HashMap的特性与应用等。通过丰富的示例代码帮助读者理解集合类的运作机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、可变参数

1、概念:

​ 是jdk1.5的新特性,应用于方法参数列表中。主要是为了解决要写很多重载方法的情况。

​ 特点:

​ (1)可变参数的参数们都是相同类型的

​ (2)一个方法只能有一个可变参数(方法参数列表中可以同时有可变参数和非可变参数)

​ (3)可变参数需要放在方法参数列表的最后面

2、格式:

修饰符 返回值类型 方法名(数据类型... 变量名){

}

(和普通方法相比,在数据类型后面添加…即可)

3、可变参数的好处

​ 是一个可变参数的反方法,可以传入任意多个参数,就不用写多个重载方法,简化代码。

4、底层原理:

​ 可变参数的实际上是一个数组。(见下面代码)

public static void main(String[] args) {
        // add();
        int x = add(1, 2, 3, 4, 5, 6);
        System.out.println(x);
    }

    // 定义一个可变参数的方法
    public static int add(int... a) {
        // System.out.println(a); // 输出结果是[I@1c53fd30,是一个地址值。

//从反编译工具编译该java文件得出:可变参数的实际上是一个数组
        
/*反编译结果
     public static void main(String args[])
   {
      int x = add(new int[] {  //调用静态方法add()
         1, 2, 3, 4, 5, 6
      });
      System.out.println(x);
   }

   public static transient int add(int a[])//静态方法
   {
      int sum = 0;
      for (int i = 0; i < a.length; i++)
         sum += a[i];

      return sum;
   }
*/

        // 遍历数组得到所有的参数
        int sum = 0;
        for (int i = 0; i < a.length; i++) {
            sum += a[i];
        }

        return sum;
    }

// 1.一个方法只能有一个可变参数
    // public static void test01(int... a, String... b) {//报错
    // }


 // 2.可变参数需要放在参数列表的最后面
    // public static void test01(int... a, String b) {//报错
    // }

2、Collection集合类的常用方法

1、概念:

​ Collections是集合工具类,里面提供了很多操作集合的方法。

​ 这个类没有看到构造方法,里面的方法全是静态方法,我们直接使用类名调用

2、常用方法
static <T> boolean addAll(Collection<?> c, T... elements) //将后面的数据添加到前面的集合中
static void shuffle(List<?> list) //随机交换集合中的元素
static void sort(List<T> list) //根据元素的自然顺序升序排

​ PS:第三个方法sort();若比较的是字符串,见一下代码:

ArrayList<String> list2 = new ArrayList<>();
Collections.addAll(list2, "b","a","d","bc","bb","ca");

Collections.sort(list2);
//按照字母的ASCII码值来排序,先全部按照第一个排序;多个字母的再进行比较(如果第一个相同,再比较第二个字母)
System.out.println("排序后: " + list2); // 排序后: [a, b, bb, bc, ca, d]
3、Comparator比较器

​ Comparator是一个接口。在Collections类中的sort();重载方法中有用到,该方法通过根据指定的排序规则来对集合中的数据进行排序。

static <T> void sort(List<T> list, Comparator<? super T> c)

​ PS: Comparator是一个接口,它作为sort方法的参数之一。(运用多态传入该接口的实现类对象)见以下代码。

学生类

public class Student {
    private String name;
    private int age;
private double socre;
//构造方法
//getter setter
//重写toString()
}

重写Comparrator接口的compare方法的类(当运用匿名内部类的时候此代码可省略)

public class StudentComparator implements Comparator<Student> {//如果此处的接口没有指定泛型,就会默认是Object类型
    @Override
    public int compare(Student o1, Student o2) {//此处重写Comparator接口的compare()方法
        // 比较学生年龄: o1 - o2升序
        // return o1.getAge() - o2.getAge();
        // 比较学生年龄: o2 - o1降序
        // return o2.getAge() - o1.getAge();

        // 按照学生成绩降序
        return (int)(o2.getSocre() - o1.getSocre());
    }
}

测试类

public static void main(String[] args) {
    ArrayList<Student> list = new ArrayList<>();
    Student s1 = new Student("赤木晴子", 16, 99);
    Student s2 = new Student("赤木刚宪", 19, 100);
    Student s3 = new Student("宫城良田", 20, 59);

    Collections.addAll(list, s1, s2, s3);

    // static <T> void sort(List<T> list, Comparator<? super T> c) 根据指定的排序规则来对集合中的数据进行排序
    // Comparator是一个接口,方法参数要接口,我们传入接口的实现类对象
    StudentComparator sc = new StudentComparator();
    Collections.sort(list, sc);

    System.out.println("方法一");
    for (Student student : list) {
        System.out.println(student);
    }

    // 方法参数要接口,我们传入匿名内部类
    Collections.sort(list, new Comparator<Student>() {
        @Override
        public int compare(Student o1, Student o2) {
            // // 按照学生成绩升序
            return (int)(o1.getSocre() - o2.getSocre());
        }
    });

    System.out.println("方法er");
    for (Student student : list) {
        System.out.println(student);
    }

}

3、冒泡排序

1、原理:

​ 相邻元素比较,大的往后放。(就像水里的泡泡往上升一样,越往上的泡泡越大)

2、分析:
分析:
    第一轮:
            j         j+1
        arr[0] 和 arr[1]
        arr[1] 和 arr[2]
        arr[2] 和 arr[3]

    第二轮:
        arr[0] 和 arr[1]
        arr[1] 和 arr[2]

    第三轮:
        arr[0] 和 arr[1]
        
  总结:(1)有i个元素比较,就要进行(i-1)轮比较
  	   (2)第一轮比较次数为i-1次,其后每经过一轮,每一轮的比较次数-1;
3、代码实现
public static void main(String[] args) {
    int[] arr = {5, 2, 3, 1};

    // 外循环控制比较轮数
    for (int i = 0; i < arr.length - 1; i++) { // i = 0,1,2
        System.out.println("轮数");

        // 内循环控制每轮的比较次数, j小于几就比较几次
        for (int j = 0; j < arr.length - 1 - i; j++) {
            // System.out.println("\t" + j + "和" + (j+1) + "比较");
            // 相邻元素比较,大的往后放
            if (arr[j] > arr[j+1]) {
                // 前面大,后面小,交换位置
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }

    System.out.println("排序后:" + Arrays.toString(arr));
}

4、Map集合

1、介绍

​ (1)Map集合是与Collection集合无关的另外一种集合接口。

​ (2)Map集合是存放一种表示映射关系的对象的集合,这种关系是一一对应得。

​ (3)这种映射关系为“键”映射到“值”的对象。

​ a. Map不能包含重复的键,但是值可以重复

​ b.每个键可以映射到最多一个值

总结:

Map集合特点:
    1.保存键和值
    2.键不能重复,值可以重复
    3.一个键对应一个值
2、Map的常用方法

​ Map是一个集合,常用的方法就是增删改查

增&改 V put(K key, V value)当键不重复是添加键值对,返回null,当键存在是修改,返回被修改的数据
V get(Object key) 通过键获取值
**删 **V remove(Object key) 通过键删除这个键值对
查集合大小 int size() 获取map的键值对的个数

补充:boolean containsKey(String key) 判断map中是否包含指定的键,如果包含返回true

public static void main(String[] args) {
    HashMap<String, String> map = new HashMap<>();

    // V put(K key, V value) 当键不重复是添加键值对,返回null,当键存在是修改,返回被修改的数据
    map.put("邓超", "孙俪");
    map.put("黄晓明", "杨颖");
    System.out.println(map.put("谢霆锋", "张柏芝")); //键不重复,put方法返回 null
    map.put("老干爹", "老干妈");

    System.out.println(map.put("谢霆锋", "王菲")); // 键重复,put方法返回 张柏芝(被修改)

    System.out.println(map);

    // V get(Object key) 通过键获取值
    System.out.println(map.get("老干爹")); // 老干妈

    // V remove(Object key) 通过键删除这个键值对
    map.remove("老干爹");
    System.out.println("删除后: " + map);

    // int size() 获取map的键值对的个数
    System.out.println(map.size());
}
3、Map的实现类HashMap:

​ hashMap的底层是哈希表

构造格式

HashMap<K, V> map = new HashMap<>();

​ PS:(K(Key)表示键的数据类型,V(Value)表示值的数据类型)

1、遍历

​ Map遍历就是依次取出每个键和值(一次获取一对)

(1)键找值方式步骤:

​ 1.获取所有的键------------->Set keySet(): 返回map中所有的键,存放到Set集合中
​ 2.遍历获取每个键----------> for循环
​ 3.通过键找值-----------------> V value = map.get(key)

代码实现

public static void main(String[] args) {
    HashMap<String, String> map = new HashMap<>();
    map.put("邓超", "孙俪");
    map.put("黄晓明", "杨颖");
    map.put("谢霆锋", "张柏芝");
    map.put("老干爹", "老干妈");
    // 1.获取所有的键
    Set<String> keySet = map.keySet();
    // 2.遍历获取每个键
    for (String key : keySet) {
    // 3.通过键找值
        String value = map.get(key); // 核心,通过键找到值
        System.out.println(key + ":::" + value);
    }
}

(2)遍历Entry方式

​ 1、Entry概念

​ Entry是Map接口内部的一个接口,表示键值对对象,里面会保存键和值,Entry相当于结婚证。

​ 2、如何获取entry

​ Set<Map.Entry<K,V>> set集合名字 = hashMap名字.entrySet(): 获取所有的Entry

​ 注意:(1)Map接口中没有获取一个Entry的方法,只能获取所有Entry)

​ (2)其中,Map.Entry<K,V>表示键值对类型;entrySet()是Map接口中返回Set集合(该集合的元素类型为键值对类型)的一个成员方法。

​ 3、步骤

​ 1.得到所有的Entry-----------> Set<Map.Entry<K,V>> set集合名字 = hashMap名字.entrySet()
​ 2.遍历得到每个Entry
​ 3.通过Entry得到键和值----------->Entry名.getKey()得到键;Entry名.getValue()得到值

public static void main(String[] args) {
    HashMap<String, String> map = new HashMap<>();
    map.put("邓超", "孙俪");
    map.put("黄晓明", "杨颖");
    map.put("谢霆锋", "张柏芝");
    map.put("老干爹", "老干妈");

    // 1.得到所有的Entry
    Set<Map.Entry<String, String>> entrySet = map.entrySet();
    // 2.遍历得到每个Entry
    for (Map.Entry<String, String> entry : entrySet) {
        // 3.通过Entry得到键和值
        System.out.println(entry.getKey() + "==" + entry.getValue());
    }
}
2、HashMap存储自定义类型

​ 也就是保证hashMap集合的元素种的键不重复。又因为hashSet的底层是哈希表,所以要保证键不重复,则需要重写键的hashCode和equals方法

​ 应用举例:

​ 需求:每位学生(姓名,年龄)都有自己的家庭住址。那么,既然有对应关系,则将学生对象和家庭住址存储到map集合中。学生作为键, 家庭住址作为值。

学生类

public class Student {
    private String name;
    private int age;
    //构造方法
//getter setter
//重写toString()
   
//需要重写键的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;
    }
public static void main(String[] args) {
    // 1.定义学生类
    // 2.创建一个Map用于存放学生
    HashMap<Student, String> map = new HashMap<>();

    // 3.创建4个学生存储到Map中
    Student s1 = new Student("流川枫", 18);
    Student s2 = new Student("樱木花道", 17);
    Student s3 = new Student("赤木晴子", 16);
    Student s4 = new Student("三井寿", 19);
    Student s5 = new Student("三井寿", 19);

    map.put(s1, "北海道");
    map.put(s2, "东京");
    map.put(s3, "大版");
    map.put(s4, "名古屋");
    map.put(s5, "广岛");

    // 4.遍历map
    // 1.键找值方式
    Set<Student> keySet = map.keySet();
    for (Student key : keySet) {
        String value = map.get(key);
        System.out.println(key + " == " + value);
    }

    System.out.println("-------------");
    // 2.Entry方式
    Set<Map.Entry<Student, String>> entrySet = map.entrySet();
    for (Map.Entry<Student, String> entry : entrySet) {
        System.out.println(entry.getKey() + "::" + entry.getValue());
    }
}
3、HashMap的应用场景以及其常用常用方法和遍历的综合应用

​ 当有对应关系的时候就使用map。

应用举例:

​ 需求:计算一个字符串中每个字符出现次数。

分析:
    一个字母会对应一个次数,有对应关系就使用Map集合来存储,字母作为键,次数作为值

实现步骤:
    1.定义一个字符串
    2.创建一个Map,字母作为键,次数作为值
    3.遍历字符串,得到每个字母
    4.如果map中没有这个字母,次数设置为1次
    5.如果map中有这个字母,次数+1
    6.遍历map集合
public static void main(String[] args) {
    // 1.定义一个字符串
    String str = "bzcbzaabAaacb";
    // 2.创建一个Map,字母作为键,次数作为值
    HashMap<Character, Integer> map = new HashMap<>();

    // 3.遍历字符串,得到每个字母
    for (int i = 0; i < str.length(); i++) {
        // 通过索引得到字符
        char c = str.charAt(i);

        // Map方法: boolean containsKey(Object key) 判断map是否有这个键
        if (map.containsKey(c)) {
            // 5.如果map中有这个字母,次数+1
            // 通过键找值,得到字符c之前已有的次数
            int cout = map.get(c);
            // 次数+1
            map.put(c, cout + 1);
        } else {
            // 4.如果map中没有这个字母,次数设置为1次
            map.put(c, 1);
        }
    }

    // 6.遍历map集合
    // Entry方式
    Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();
    for (Map.Entry<Character, Integer> entry : entrySet) {
        System.out.println(entry.getKey() + ": " + entry.getValue());
    }
}
4、图书馆管理系统
/*
功能分析:
    1.功能选择界面
    2.初始化书籍
    3.查看书籍
    4.添加书籍
    5.删除书籍
    6.修改书籍

目标:实现 1.功能选择界面
    打印输出相应字符串即可
    使用键盘输入
    根据用户的输入进行选择

目标:实现 2.初始化书籍
    1.定义Book书籍类
    2.创建一个名著集合,存储两本名著
    3.创建一个it书籍集合,存储两本it书籍
    4.创建一个Map,键是书籍类型,值就是对应的书籍集合
    5.添加对应的数据到Map集合中

目标:实现 3.查看书籍
    遍历map集合

目标:实现 4.添加书籍
    输入要添加书籍的类型
    输入要添加的书名
    输入要添加书的价格
    创建Book对象
    添加到对应的ArrayList集合中

目标: 实现 5.删除书籍
    输入要删除书籍的类型
    输入要删除的书名
    通过类型找到书籍的集合
    从集合中删除这本数

目标: 实现 6.修改书籍
    输入要修改书籍的类型
    输入要修改书籍的书名
    输入新的书名
    输入新的价格
    通过类型找到书籍的集合
    遍历书籍集合找到要修改的书籍
    修改书籍
 */
public static void main(String[] args) {
    // 2.初始化书籍
    // 1.定义Book书籍类
    // 2.创建一个名著集合,存储两本名著
    ArrayList<Book> mz = new ArrayList<>();
    mz.add(new Book("西游记", 19));
    mz.add(new Book("水浒传", 29));

    // 3.创建一个it书籍集合,存储两本it书籍
    ArrayList<Book> it = new ArrayList<>();
    it.add(new Book("Java入门到精通", 99));
    it.add(new Book("PHP入门到精通", 9.9));

    // 4.创建一个Map,键是书籍类型,值就是对应的书籍集合
    HashMap<String, ArrayList<Book>> map = new HashMap<>();

    // 5.添加对应的数据到Map集合中
    map.put("名著", mz);
    map.put("it书籍", it);

    // 让功能选择界面可以循环多次选择
    while (true) {
        // 1.功能选择界面, 打印输出相应字符串即可
        System.out.println("--------欢迎来到图书管理系统--------");
        System.out.println("1.查看书籍");
        System.out.println("2.添加书籍");
        System.out.println("3.删除书籍");
        System.out.println("4.修改书籍");
        System.out.println("5.退出");
        // 使用键盘输入
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入你的选择:");
        int operator = sc.nextInt();

        // 根据用户的输入进行选择
        switch (operator) {
            case 1:
                showAllBooks(map);
                break;
            case 2:
                addBook(map);
                break;
            case 3:
                deleteBook(map);
                break;
            case 4:
                updateBook(map);
                break;
            case 5:
                System.out.println("大爷,请慢走,欢迎下次再来!");
                System.exit(0);
                break;
            default:
                System.out.println("大爷,你的操作不存在.请不要乱来");
                break;
        }
    }
}

private static void updateBook(HashMap<String, ArrayList<Book>> map) {
    // 目标: 实现 6.修改书籍
    Scanner sc = new Scanner(System.in);
    //  输入要修改书籍的类型
    System.out.println("请输入要修改书籍的类型");
    String type = sc.next();

    //  输入要修改书籍的书名
    System.out.println("请输入要修改书籍的书名");
    String oldName = sc.next();

    //  输入新的书名
    System.out.println("请输入新的书名");
    String newName = sc.next();
    //  输入新的价格
    System.out.println("请输入新的价格");
    double newPrice = sc.nextDouble();

    //  通过类型找到书籍的集合
    ArrayList<Book> list = map.get(type);
    if (list == null) {
        System.out.println("要修改的书籍类型不存在");
        return;
    }
    //  遍历书籍集合找到要修改的书籍
    for (int i = 0; i < list.size(); i++) {
        Book book = list.get(i);
        if (book.getName().equals(oldName)) {
            // 找到了要修改的书籍
            //  修改书籍
            book.setName(newName);
            book.setPrice(newPrice);
            System.out.println("修改" + oldName + "成功");
            return;
        }
    }

    System.out.println("没有找要修改的书籍" + oldName);
}

private static void deleteBook(HashMap<String, ArrayList<Book>> map) {
    // 目标: 实现 5.删除书籍
    Scanner sc = new Scanner(System.in);
    //  输入要删除书籍的类型
    System.out.println("请输入要删除书籍的类型");
    String type = sc.next();
    //  输入要删除的书名
    System.out.println("请输入要删除的书名");
    String name = sc.next();

    //  通过类型找到书籍的集合
    ArrayList<Book> list = map.get(type);

    if (list == null) {
        System.out.println("没有这个类型的书籍");
        return;
    }

    //  从集合中删除这本数
    for (int i = 0; i < list.size(); i++) {
        Book book = list.get(i);
        if (book.getName().equals(name)) {
            // 找到要删除的书籍,并删除
            list.remove(i);
            System.out.println("删除" + name + "成功");
            return ; // 结束这个方法
        }
    }

    System.out.println("没有这本书籍" + name);
}

private static void addBook(HashMap<String, ArrayList<Book>> map) {
    // 目标:实现 4.添加书籍
    Scanner sc = new Scanner(System.in);
    //  输入要添加书籍的类型
    System.out.println("请输入要添加书籍的类型");
    String type = sc.next();
    //  输入要添加的书名
    System.out.println("请输入要添加的书名");
    String name = sc.next();
    //  输入要添加书的价格
    System.out.println("请输入要添加书的价格");
    double price = sc.nextDouble();
    //  创建Book对象
    Book book = new Book(name, price);

    // 通过书籍类型,【找到】书籍集合
    ArrayList<Book> list = map.get(type);

    // 如果list为null说明,没有这种类型的书籍
    if (list == null) {
        list = new ArrayList<>();
        map.put(type, list);
    }

    // 判断书籍是否存在
    // 做一个标记,表示这本书是否存在,false表示不存在
    boolean exists = false;
    for (Book b : list) {
        if (b.getName().equals(name)) {
            // 书名相同;
            exists = true;
            break; // 一旦书名相同,就是重复的书籍,不需要往后面判断啦
        }
    }

    if (exists) {
        // 如果存在,就不添加
        System.out.println(name + "书籍已经存在");
    } else {
        // 如果不存在,就添加

        //  添加到对应的ArrayList集合中
        list.add(book);
        System.out.println("添加" + name + "书籍成功");
    }
}

private static void showAllBooks(HashMap<String, ArrayList<Book>> map) {
    System.out.println("类型\t\t书名\t价格");
    // 遍历Map,使用Entry方式
    // 1.得到所有的Entry
    Set<Map.Entry<String, ArrayList<Book>>> entrySet = map.entrySet();
    // 2.遍历得到每个Entry
    for (Map.Entry<String, ArrayList<Book>> entry : entrySet) {
        // 打印键
        System.out.println(entry.getKey());

        // 得到值(ArrayList集合)
        ArrayList<Book> value = entry.getValue();
        // 遍历打印ArrayList
        for (Book book : value) {
            System.out.println("\t\t\t" +book.getName() + "\t" + book.getPrice());
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值