day06-排序查找算法,Map集合,集合嵌套,斗地主案例

今日目标 :

  • TreeSet集合(重点)
  • 排序算法(理解)
  • 查找算法(理解)
  • Map集合(重点)
  • 集合嵌套(理解)
  • 斗地主案例(理解)

1 TreeSet集合

1.1 集合体系

  • Collection

    • List接口

      • ArrayList类
      • LinkedList类
    • Set接口

      • HashSet集合

      • TreeSet集合

1.2 TreeSet特点

  • 不包含重复元素的集合[元素唯一]
  • 没有带索引的方法[无索引]
  • 可以按照指定的规则进行排序[可以排序]

1.3 TreeSet集合的练习

  1. package com.itheima.treeset_demo;
  2. import java.util.Iterator;
  3. import java.util.TreeSet;
  4. /*
  5. 1 TreeSet集合练习
  6. 存储Integer类型的整数,并遍历
  7. */
  8. public class TreeSetDemo {
  9. public static void main(String[] args) {
  10. TreeSet<Integer> ts = new TreeSet<>();
  11. ts.add(10);
  12. ts.add(10);
  13. ts.add(20);
  14. ts.add(10);
  15. ts.add(30);
  16. // 迭代器
  17. Iterator<Integer> it = ts.iterator();
  18. while(it.hasNext()){
  19. Integer s = it.next();
  20. System.out.println(s);
  21. }
  22. System.out.println("================");
  23. // 增强for
  24. for (Integer t : ts) {
  25. System.out.println(t);
  26. }
  27. }
  28. }
  • 如果TreeSet存储自定义对象 , 需要对自定义类进行指定排序规则
    下列代码没有指定排序规则 , 所以运行会报出错误
  1. package com.itheima.treeset_demo;
  2. public class Student {
  3. private String name;
  4. private int age;
  5. public Student() {
  6. }
  7. public Student(String name, int age) {
  8. this.name = name;
  9. this.age = age;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public int getAge() {
  18. return age;
  19. }
  20. public void setAge(int age) {
  21. this.age = age;
  22. }
  23. @Override
  24. public String toString() {
  25. return "Student{" +
  26. "name='" + name + '\'' +
  27. ", age=" + age +
  28. '}';
  29. }
  30. }
  31. =============================================================
  32. package com.itheima.treeset_demo;
  33. import java.util.Iterator;
  34. import java.util.TreeSet;
  35. /*
  36. TreeSet集合练习
  37. 存储学生对象,并遍历
  38. */
  39. public class TreeSetDemo2 {
  40. public static void main(String[] args) {
  41. TreeSet<Student> ts = new TreeSet<>();
  42. Student s1 = new Student("dilireba", 19);
  43. Student s2 = new Student("gulinazha", 20);
  44. Student s3 = new Student("maerzhaha", 18);
  45. ts.add(s1);
  46. ts.add(s2);
  47. ts.add(s3);
  48. System.out.println(ts);
  49. }
  50. }

1.4 排序规则

1.4.1 自然排序

  • 使用步骤
  • 使用空参构造创建TreeSet集合对象
  • 存储元素所在的类需要实现Comparable接口
  • 重写Comparable接口中的抽象方法 compareTo方法,指定排序规则
    • compareTo方法如何指定排序规则 :
  • 此方法如果返回的是小于0 , 代表的是当前元素较小 , 需要存放在左边
  • 此方法如果返回的是大于0 , 代表的是当前元素较大, 需要存放在右边
  • 此方法如果返回的是0 , 代表的是当前元素在集合中已经存在 , 不存储
    • 练习 : 存储学生对象, 按照年龄的升序排序,并遍历
  1. package com.itheima.treeset_demo;
  2. public class Student implements Comparable<Student>{
  3. private String name;
  4. private int age;
  5. public Student() {
  6. }
  7. public Student(String name, int age) {
  8. this.name = name;
  9. this.age = age;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public int getAge() {
  18. return age;
  19. }
  20. public void setAge(int age) {
  21. this.age = age;
  22. }
  23. @Override
  24. public String toString() {
  25. return "Student{" +
  26. "name='" + name + '\'' +
  27. ", age=" + age +
  28. '}';
  29. }
  30. /*
  31. */
  32. @Override
  33. public int compareTo(Student o) {
  34. /*
  35. this : 当前要添加的元素
  36. o : 集合中已经存在的元素
  37. 如果方法返回值为负数 : 当前元素放左边
  38. 如果方法的返回值为正数 : 当前元素放右边
  39. 如果方法的返回值为0 : 说明当前元素在集合中存在,不存储
  40. */
  41. int result = this.age - o.age;
  42. return result;
  43. }
  44. }
  45. =====================================================
  46. package com.itheima.treeset_demo;
  47. import java.util.Iterator;
  48. import java.util.TreeSet;
  49. /*
  50. TreeSet集合练习
  51. 存储学生对象,并遍历
  52. */
  53. public class TreeSetDemo2 {
  54. public static void main(String[] args) {
  55. TreeSet<Student> ts = new TreeSet<>();
  56. Student s1 = new Student("dilireba", 19);
  57. Student s2 = new Student("gulinazha", 20);
  58. Student s3 = new Student("maerzhaha", 18);
  59. ts.add(s1);
  60. ts.add(s2);
  61. ts.add(s3);
  62. System.out.println(ts);
  63. }
  64. }
  • 对刚才的案例进行改进 , 如果年龄相等 , 那么对学生的名字在字典的顺序排序
  1. package com.itheima.treeset_demo;
  2. public class Student implements Comparable<Student> {
  3. private String name;
  4. private int age;
  5. public Student() {
  6. }
  7. public Student(String name, int age) {
  8. this.name = name;
  9. this.age = age;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public int getAge() {
  18. return age;
  19. }
  20. public void setAge(int age) {
  21. this.age = age;
  22. }
  23. @Override
  24. public String toString() {
  25. return "Student{" +
  26. "name='" + name + '\'' +
  27. ", age=" + age +
  28. '}';
  29. }
  30. /*
  31. */
  32. @Override
  33. public int compareTo(Student o) {
  34. /*
  35. this : 当前要添加的元素
  36. o : 集合中已经存在的元素
  37. 如果方法返回值为负数 : 当前元素放左边
  38. 如果方法的返回值为正数 : 当前元素放右边
  39. 如果方法的返回值为0 : 说明当前元素在集合中存在,不存储
  40. */
  41. int result = this.age - o.age;
  42. // 如果年龄相等 , 那么按照名字进行排序
  43. return result == 0 ? this.name.compareTo(o.name) : age;
  44. }
  45. }
  46. =============================================================
  47. package com.itheima.treeset_demo;
  48. import java.util.Iterator;
  49. import java.util.TreeSet;
  50. /*
  51. TreeSet集合练习
  52. 存储学生对象, 按照年龄的升序排序,并遍历
  53. */
  54. public class TreeSetDemo2 {
  55. public static void main(String[] args) {
  56. TreeSet<Student> ts = new TreeSet<>();
  57. Student s1 = new Student("dilireba", 19);
  58. Student s2 = new Student("gulinazha", 20);
  59. Student s3 = new Student("maerzhaha", 18);
  60. Student s4 = new Student("ouyangnanan", 18);
  61. ts.add(s1);
  62. ts.add(s2);
  63. ts.add(s3);
  64. ts.add(s4);
  65. System.out.println(ts);
  66. }
  67. }

1.4.2 比较器排序

  • 使用步骤
  • TreeSet的带参构造方法使用的是 “比较器排序” 对元素进行排序的
  • 比较器排序,就是让TreeSet集合构造方法接收Comparator接口的实现类对象
  • 重写Comparator接口中的 compare(T o1,T o2)方法 , 指定排序规则
  • 注意 : o1代表的是当前往集合中添加的元素 , o2代表的是集合中已经存在的元素,排序原理与自然排序相同!
    • 排序规则
  • 排序原理与自然排序相同!
    • 练习
  1. package com.itheima.treeset_demo.comparator_demo;
  2. public class Teacher {
  3. private String name;
  4. private int age;
  5. public Teacher() {
  6. }
  7. public Teacher(String name, int age) {
  8. this.name = name;
  9. this.age = age;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public int getAge() {
  18. return age;
  19. }
  20. public void setAge(int age) {
  21. this.age = age;
  22. }
  23. @Override
  24. public String toString() {
  25. return "Student{" +
  26. "name='" + name + '\'' +
  27. ", age=" + age +
  28. '}';
  29. }
  30. }
  31. ======================================
  32. package com.itheima.treeset_demo.comparator_demo;
  33. import java.util.Comparator;
  34. import java.util.TreeSet;
  35. /*
  36. TreeSet集合练习
  37. 存储学生对象, 按照年龄的升序排序,并遍历
  38. */
  39. public class TreeSetDemo2 {
  40. public static void main(String[] args) {
  41. TreeSet<Teacher> ts = new TreeSet<>(new ComparatorImpl());
  42. Teacher s1 = new Teacher("dilireba", 19);
  43. Teacher s2 = new Teacher("gulinazha", 20);
  44. Teacher s3 = new Teacher("maerzhaha", 18);
  45. Teacher s4 = new Teacher("ouyangnanan", 18);
  46. ts.add(s1);
  47. ts.add(s2);
  48. ts.add(s3);
  49. ts.add(s4);
  50. System.out.println(ts);
  51. }
  52. }
  53. // 比较器排序
  54. class ComparatorImpl implements Comparator<Teacher> {
  55. @Override
  56. public int compare(Teacher o1, Teacher o2) {
  57. int result = o1.getAge() - o2.getAge();
  58. return result == 0 ? o1.getName().compareTo(o2.getName()) : result;
  59. }
  60. }

1.4.3 两种排序的区别

  • 自然排序:自定义类实现Comparable接口,重写compareTo方法,根据返回值进行排序。

  • 比较器排序:创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序。

  • 如果Java提供好的类已经定义了自然排序排序规则 , 那么我们可以使用比较器排序进行替换

  • 注意 : 如果自然排序和比较器排序都存在 , 那么会使用比较器排序

  • 两种方式中,关于返回值的规则:

    • 如果返回值为负数,表示当前存入的元素是较小值,存左边
    • 如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存
    • 如果返回值为正数,表示当前存入的元素是较大值,存右边

2 Collections单列集合工具类

  • Collections工具类介绍

    • java.util.Collections 是集合的工具类,里面提供了静态方法来操作集合,乱序,排序….

2.1 shuffle方法

  • public static void shuffle(List<?> list) 对集合中的元素进行打乱顺序。

  • 集合中元素类型可以任意类型 ```java package com.itheima.collections_demo;

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

/* Collections类 : 操作单列集合的工具类 public static void shuffle(List<?> list) 对集合中的元素进行打乱顺序 1 乱序只能对List集合进行乱序 2 集合中元素类型可以任意类型

  1. 需求 : 定义一个List集合,里面存储若干整数。对集合进行乱序

*/ public class ShuffleDemo { public static void main(String[] args) { ArrayList list = new ArrayList<>(); list.add(10); list.add(30); list.add(50); list.add(40); list.add(20);

  1. Collections.shuffle(list);
  2. System.out.println(list);// 打印集合中的元素
  3. }

}

  1. <a name="dc88bc94"></a>
  2. ### 2.2 sort方法
  3. -
  4. public static void sort (List list): 对集合中的元素自然排序
  5. - 该方法只能对List集合进行排序
  6. - 从方法中泛型分析可知,集合中元素类型必须是Comparable的子类型
  7. ```java
  8. package com.itheima.collections_demo;
  9. import java.util.ArrayList;
  10. import java.util.Collections;
  11. import java.util.Comparator;
  12. /*
  13. Collections类 : 单列集合的工具类
  14. sort方法是一个重载的方法,可以实现自然排序及比较器排序。
  15. 要特别注意的是sort方法只能对List集合进行排序,方法如下:
  16. public static <T extends Comparable> void sort (List<T> list)
  17. 练习:定义List集合,存储若干整数,进行排序
  18. */
  19. public class SortDemo1 {
  20. public static void main(String[] args) {
  21. ArrayList<Integer> list = new ArrayList<>();
  22. list.add(3);
  23. list.add(2);
  24. list.add(4);
  25. list.add(1);
  26. // 使用此方法 , 需要集合中存储的元素实现Comparable接口
  27. Collections.sort(list);
  28. System.out.println(list);
  29. }
  30. }
  • public static void sort (List list, Comparator<? super T> c)

    • 方法只能对List集合排序

    • 对元素的类型没有要求

    • 需要定义一个比较器Comparator (规则和之前TreeSet时一样)

    • 使用场景:

      • List集合中的元素类型不具备自然排序能力(元素类型没有实现结果 Comparable)
      • List集合中的元素类型具备自然排序能力,但是排序规则不是当前所需要的。 ```java package com.itheima.collections_demo;

import java.util.ArrayList; import java.util.Collections; import java.util.Comparator;

/* Collections类 : 单列集合的工具类 sort方法是一个重载的方法,可以实现自然排序及比较器排序。 要特别注意的是sort方法只能对List集合进行排序,方法如下:

  1. public static <T extends Comparable> void sort (List<T> list) : 只能对集合中的元素自然排序
  2. 需求1:定义一个List集合,存储若干整数,要求对集合进行降序排序
  3. 分析:整数类型Integer具备自然排序能力,但是题目要求降序排序
  4. 需求2:定义一个学生类,属性有姓名,年龄。创建若干对象放到List集合中。要求对List集合中学生对象进行年龄的升序排序。
  5. 分析:自定义类型默认是没有自然排序能力的,我们使用自定义比较器方式排序。

*/ public class SortDemo2 { public static void main(String[] args) {

  1. /*
  2. 需求2:定义一个学生类,属性有姓名,年龄。创建若干对象放到List集合中。要求对List集合中学生对象进行年龄的升序排序。
  3. 分析:自定义类型默认是没有自然排序能力的,我们使用自定义比较器方式排序
  4. */
  5. ArrayList<Student> list = new ArrayList<>();
  6. list.add(new Student("lisi", 24));
  7. list.add(new Student("zhangsan", 23));
  8. Collections.sort(list, new Comparator<Student>() {
  9. @Override
  10. public int compare(Student o1, Student o2) {
  11. return o1.getAge() - o2.getAge();
  12. }
  13. });
  14. System.out.println(list);
  15. }
  16. /*
  17. 需求1:定义一个List集合,存储若干整数,要求对集合进行降序排序
  18. 分析:整数类型Integer具备自然排序能力,但是题目要求降序排序
  19. */
  20. private static void method1() {
  21. ArrayList<Integer> list = new ArrayList<>();
  22. list.add(3);
  23. list.add(2);
  24. list.add(4);
  25. list.add(1);
  26. // 使用此方法 , 需要集合中存储的元素实现Comparable接口
  27. Collections.sort(list, new Comparator<Integer>() {
  28. @Override
  29. public int compare(Integer o1, Integer o2) {
  30. return o2 - o1;
  31. }
  32. });
  33. System.out.println(list);
  34. }

}

  1. <a name="41cd90f7"></a>
  2. ## 3 可变参数
  3. <a name="30bf6357"></a>
  4. ### 3.1 可变参数介绍
  5. - 在 JDK5 中提供了可变参数,允许在调用方法时传入任意个参数。可变参数原理就是一个数组形式存在
  6. - 格式 : 修饰符 返回值类型 方法名(数据类型… 变量名) { }
  7. - 举例 : public void show(int ... num) : 表达式该方法可以接收任意个整数值 , 原理 : 其实就是一个int类型的数组
  8. <a name="9e4e248f"></a>
  9. ### 3.2 可变参数注意
  10. - 可变参数只能作为方法的最后一个参数,但其前面可以有或没有任何其他参数。
  11. - 可变参数本质上是数组,不能作为方法的重载。如果同时出现相同类型的数组和可变参数方法,是不能编译通过的。
  12. <a name="d6572b8b"></a>
  13. ### 3.3 可变参数的使用
  14. - 调用可变参数方法,可以给出零到任意多个参数,编译器会将可变参数转化为一个数组,也可以直接传递一个数组。<br />
  15. 方法内部使用时直接当做数组使用即可
  16. ```java
  17. package com.itheima.changevariable_demo;
  18. /*
  19. 1 什么是可变参数
  20. JDK5中,允许在调用方法时传入任意个参数。可变参数原理就是一个数组形式存在
  21. 格式 : 修饰符 返回值类型 方法名(数据类型… 变量名) { }
  22. 举例 : public void show(int... num){}
  23. 2 可变参数注意 :
  24. 1) 可变参数只能作为方法的最后一个参数,但其前面可以有或没有任何其他参数。
  25. 2) 可变参数本质上是数组,不能作为方法的重载。如果同时出现相同类型的数组和可变参数方法,是不能编译通过的。
  26. 3 可变参数的使用 :
  27. 调用可变参数的方法 , 可以传入0个到任意个数据 , 编译器会将可变参数转换成一个数组 , 也可以直接传递一个数组
  28. 方法中把可变参数当做一个数组去使用即可
  29. 练习:定义方法可以求任意个整数的和
  30. */
  31. public class VariableDemo1 {
  32. public static void main(String[] args) {
  33. sum();
  34. sum(1, 2);
  35. sum(1, 2, 3, 4);
  36. }
  37. public static void sum(int... num) {// 方法的参数是一个int类型的可变参数
  38. int sum = 0;// 定义求和变量
  39. for (int i : num) {
  40. sum += i;
  41. }
  42. System.out.println(sum);
  43. }
  44. }

3.4 addAll方法

  • static boolean addAll(Collection<? super T> c , T… elements) : 添加任意多个数据到集合中

    • 该方法就是一个含有可变参数的方法,使用时可以传入任意多个实参,实用方便!

    • 分析 : Collection<? super T> , ? 可以是 T 的类型或者父类型 , 反过来 , T是?类型或者子类型
      那么当你确定?的类型,也就是集合的类型 , 就可以往集合中添加此类型或者子类型

  1. package com.itheima.changevariable_demo;
  2. import java.util.ArrayList;
  3. import java.util.Collections;
  4. /*
  5. Collections的addAll方法
  6. static <T> boolean addAll(Collection<? super T> c , T... elements) : 添加任意多个数据到集合中
  7. 分析: 该方法就是一个含有可变参数的方法,使用时可以传入任意多个实参,实用方便!
  8. 练习:创建一个List集合,使用addAll方法传入若干字符串
  9. */
  10. public class VariableDemo2 {
  11. public static void main(String[] args) {
  12. ArrayList<Integer> list = new ArrayList<>();
  13. Collections.addAll(list, 10, 20, 30, 40);
  14. System.out.println(list);// [10, 20, 30, 40]
  15. }
  16. }

4 排序,查找算法

4.1 冒泡排序

  • 冒泡排序 : 将一组数据按照从小到大的顺序进行排序
  • 冒泡排序原理 : 相邻元素两两作比较 , 大的元素往后放
  1. package com.itheima.arraysort_demo.bubblesort_demo;
  2. import java.util.Arrays;
  3. /*
  4. 冒泡排序 : 将一组数据按照从小到大的顺序进行排序
  5. 冒泡排序的原理 : 相邻元素两两作比较 , 大的元素往后放
  6. 需求 : 将数组中的元素 {3,5,2,1,4} 进行升序排序
  7. */
  8. public class SortDemo {
  9. public static void main(String[] args) {
  10. int[] arr = {3, 5, 2, 1, 4};
  11. // // 第一轮排序
  12. // for (int i = 0; i < arr.length - 1; i++) {
  13. // if (arr[i] > arr[i + 1]) {
  14. // int temp = arr[i];
  15. // arr[i] = arr[i + 1];
  16. // arr[i + 1] = temp;
  17. // }
  18. // }
  19. //
  20. // System.out.println("第一轮排序:" + Arrays.toString(arr));
  21. //
  22. //
  23. // // 第二轮排序
  24. // for (int i = 0; i < arr.length - 2; i++) {
  25. // if (arr[i] > arr[i + 1]) {
  26. // int temp = arr[i];
  27. // arr[i] = arr[i + 1];
  28. // arr[i + 1] = temp;
  29. // }
  30. // }
  31. //
  32. // System.out.println("第二轮排序:" + Arrays.toString(arr));
  33. //
  34. //
  35. // // 第三轮排序
  36. // for (int i = 0; i < arr.length - 2; i++) {
  37. // if (arr[i] > arr[i + 1]) {
  38. // int temp = arr[i];
  39. // arr[i] = arr[i + 1];
  40. // arr[i + 1] = temp;
  41. // }
  42. // }
  43. //
  44. // System.out.println("第三轮排序:" + Arrays.toString(arr));
  45. //
  46. //
  47. // // 第四轮排序
  48. // for (int i = 0; i < arr.length - 2; i++) {
  49. // if (arr[i] > arr[i + 1]) {
  50. // int temp = arr[i];
  51. // arr[i] = arr[i + 1];
  52. // arr[i + 1] = temp;
  53. // }
  54. // }
  55. //
  56. // System.out.println("第四轮排序:" + Arrays.toString(arr));
  57. // 优化代码
  58. for (int j = 0; j < arr.length - 1; j++) {// 比较的轮次
  59. // 每轮相邻元素比较的次数
  60. for (int i = 0; i < arr.length - 1 - j; i++) {
  61. if (arr[i] > arr[i + 1]) {
  62. int temp = arr[i];
  63. arr[i] = arr[i + 1];
  64. arr[i + 1] = temp;
  65. }
  66. }
  67. System.out.println("第" + (j + 1) + "轮排序:" + Arrays.toString(arr));
  68. }
  69. }
  70. }

4.2 选择排序

  • 选择排序原理 : 它的工作原理是每一次从待排序的数据元素中选出最小的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。
  • 注意事项 :

    • 有n个元素,那么就要比较n-1轮次。
    • 每一趟中都会选出一个最值元素,较前一趟少比较一次
  1. package com.itheima.arraysort_demo.selectionsort_demo;
  2. /*
  3. 选择排序工作原理 :
  4. 它的工作原理是每一次从待排序的数据元素中选出最小的一个元素,
  5. 存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾。
  6. 以此类推,直到全部待排序的数据元素排完。
  7. 注意 :
  8. 1 有n个元素,那么就要比较n-1趟。
  9. 2 每一趟中都会选出一个最值元素,较前一趟少比较一次
  10. */
  11. import java.util.Arrays;
  12. public class SortDemo {
  13. public static void main(String[] args) {
  14. int[] arr = {4, 1, 5, 3, 2};
  15. // 遍历数组
  16. for (int i = 0; i < arr.length - 1; i++) {
  17. // 记录当前元素和其之后所有元素的最小值索引
  18. int minIndex = i;
  19. int min = arr[i];
  20. for (int j = i; j < arr.length; j++) {
  21. if (arr[j] < min) {
  22. minIndex = j; // 把当前最小值的索引赋值给minIndex
  23. min = arr[j];// 替换最小值
  24. }
  25. }
  26. if (i != minIndex) {
  27. int temp = arr[i];
  28. arr[i] = arr[minIndex];
  29. arr[minIndex] = temp;
  30. }
  31. }
  32. System.out.println(Arrays.toString(arr));
  33. }
  34. }

4.3 二分查找

  • 原理 : 每次去掉一般的查找范围
  • 前提 : 数组必须有序
  1. package com.itheima.arraysort_demo.binarysearch_demo;
  2. /*
  3. 二分查找 :
  4. 原理 : 每次去掉一般的查找范围
  5. 前提 : 数组必须有序
  6. 步骤 :
  7. 1,定义两个变量,表示要查找的范围。默认min = 0 , max = 最大索引
  8. 2,循环查找,但是min <= max
  9. 3,计算出mid的值
  10. 4,判断mid位置的元素是否为要查找的元素,如果是直接返回对应索引
  11. 5,如果要查找的值在mid的左半边,那么min值不变,max = mid -1.继续下次循环查找
  12. 6,如果要查找的值在mid的右半边,那么max值不变,min = mid + 1.继续下次循环查找
  13. 7,当 min > max 时,表示要查找的元素在数组中不存在,返回-1.
  14. */
  15. public class BinarySearchDemo {
  16. public static void main(String[] args) {
  17. int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  18. int i = binarySearch(arr, 8);
  19. System.out.println(i);
  20. }
  21. public static int binarySearch(int[] arr, int num) {
  22. // 定义两个变量,表示要查找的范围。默认min = 0 , max = 最大索引
  23. int max = arr.length - 1;
  24. int min = 0;
  25. // 2,循环查找,但是min <= max
  26. while (min <= max) {
  27. // 3,计算出mid的值
  28. int mid = (min + max) / 2;
  29. if (arr[mid] == num) {
  30. // 4,判断mid位置的元素是否为要查找的元素,如果是直接返回对应索引
  31. return mid;
  32. } else if (arr[mid] > num) {
  33. // 5,如果要查找的值在mid的左半边,那么min值不变,max = mid -1.继续下次循环查找
  34. max = mid - 1;
  35. } else if (arr[mid] < num) {
  36. // 6,如果要查找的值在mid的右半边,那么max值不变,min = mid + 1.继续下次循环查找
  37. min = mid + 1;
  38. }
  39. }
  40. return -1;
  41. }
  42. }

5 Map集合

5.1 Map集合的介绍

  • java.util.Map 集合,里面保存的数据是成对存在的,称之为双列集合。存储的数据,我们称为键值对。 之前所学的Collection集合中元素单个单个存在的,称为单列集合

5.2 特点

  • Map K:键的数据类型;V:值的数据类型

  • 特点 :

    • 键不能重复,值可以重复
    • 键和值是 一 一 对应的,通过键可以找到对应的值
    • (键 + 值) 一起是一个整体 我们称之为“键值对” 或者 “键值对对象”,在Java中叫做“Entry对象”
  • 使用场景

    • 凡是要表示一一对应的数据时就可以Map集合

      • 举例 : 学生的学号和姓名 —- (itheima001 小智)
      • 举例 : 夫妻的关系 —— (王宝强 马蓉 ) (谢霆锋 张柏芝)

5.3 常用实现类

  • HashMap:

    • 此前的HashSet底层实现就是HashMap完成的,HashSet保存的元素其实就是HashMap集合中保存的键,底层结构是哈希表结构,具有键唯一,无序,特点。
  • LinkedHashMap:

    • 底层结构是有链表和哈希表结构,去重,有序
  • TreeMap:

    • 底层是有红黑树,去重,通过键排序

5.4 常用的方法

  • public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。
  • public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
  • public V get(Object key) 根据指定的键,在Map集合中获取对应的值。
  • public Set keySet(): 获取Map集合中所有的键,存储到Set集合中。
  • public boolean containKey(Object key):判断该集合中是否有此键。
  1. package com.itheima.map_demo.mapmethod_demo;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import java.util.Set;
  5. /*
  6. Map中常用方法 :
  7. public V put(K key, V value): 把指定的键与指定的值添加到Map集合中
  8. public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值
  9. public V get(Object key) 根据指定的键,在Map集合中获取对应的值
  10. public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中
  11. public boolean containKey(Object key): 判断该集合中是否有此键。
  12. 需求 : 将以下数据保存到Map集合中 , 进行测试以上方法
  13. “文章“  "马伊琍
  14. “谢霆锋”  “王菲”
  15. “李亚鹏”  “王菲”
  16. */
  17. public class MapDemo {
  18. public static void main(String[] args) {
  19. // 创建双列集合对象
  20. Map<String, String> hm = new HashMap<>();
  21. // 添加元素
  22. // public V put(K key, V value): 把指定的键与指定的值添加到Map集合中
  23. hm.put("文章", "马伊琍");
  24. hm.put("谢霆锋", "王菲");
  25. hm.put("李亚鹏", "王菲");
  26. // public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值
  27. // System.out.println(hm.remove("谢霆锋"));
  28. // public V get(Object key) 根据指定的键,在Map集合中获取对应的值
  29. // System.out.println(hm.get("李亚鹏"));
  30. // public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中
  31. // Set<String> set = hm.keySet();
  32. // for (String key : set) {
  33. // System.out.println(key);
  34. // }
  35. // public boolean containKey(Object key): 判断该集合中是否有此键。
  36. // System.out.println(hm.containsKey("李亚鹏"));
  37. System.out.println(hm);// 打印集合 , 打印的是集合中的元素
  38. }
  39. }

5.5 Map集合的遍历

  • 第一种方式 : 键找值
  1. package com.itheima.map_demo.map_test;

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

/*
创建Map集合对象 , 往集合中添加以下四对元素 , 使用键找值遍历集合

  1. 周瑜 -- 小乔
  2. 孙策 -- 大乔
  3. 刘备 -- 孙尚香
  4. 诸葛亮 -- 黄月英

*/
public class MapTest1 {
public static void main(String[] args) {
// 创建集合对象
Map hm = new HashMap<>();

  1. // 添加元素
  2. hm.put("周瑜", "小乔");
  3. hm.put("孙策", "大乔");
  4. hm.put("刘备", "孙尚香");
  5. hm.put("诸葛亮", "黄月英");
  6. // 获取健集合
  7. Set<String> set = hm.keySet();
  8. // 遍历健集合 , 通过键找值
  9. for (String key : set) {
  10. String value = hm.get(key);
  11. System.out.println(key + "---" + value);
  12. }
  13. }

}

  1. - 第二种方式 : 获取键值对对象 , 在找到键和值
  2. ```java
  3. package com.itheima.map_demo.map_test;
  4. import java.util.HashMap;
  5. import java.util.Map;
  6. import java.util.Set;
  7. /*
  8. 需求 : 创建Map集合对象 , 往集合中添加以下三对元素
  9. 使用获取Entry对象集合,在找到键和值 遍历集合
  10. 张无忌 -- 赵敏
  11. 张翠山 -- 殷素素
  12. 张三丰 -- 郭芙
  13. */
  14. public class MapTest2 {
  15. public static void main(String[] args) {
  16. // 创建集合对象
  17. Map<String, String> hm = new HashMap<>();
  18. // 添加元素
  19. hm.put("张无忌", "赵敏");
  20. hm.put("张翠山", "殷素素");
  21. hm.put("张三丰", "郭芙");
  22. // 获取键值对对象集合
  23. Set<Map.Entry<String, String>> set = hm.entrySet();
  24. // 遍历键值对对象集合 , 获取每一个键值对对象
  25. for (Map.Entry<String, String> entry : set) {
  26. // 通过entry对象获取键
  27. String key = entry.getKey();
  28. // 通过entry对象获取值
  29. String value = entry.getValue();
  30. System.out.println(key + "--" + value);
  31. }
  32. }
  33. }

5.6 HashMap集合

  • 注意 : HashMap集合 , 要想保证键唯一 , 那么键所在的类必须重写hashCode和equals方法
  1. package com.itheima.map_demo.map_test;
  2. public class Student {
  3. private String name;
  4. private int age;
  5. public Student() {
  6. }
  7. public Student(String name, int age) {
  8. this.name = name;
  9. this.age = age;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public int getAge() {
  18. return age;
  19. }
  20. public void setAge(int age) {
  21. this.age = age;
  22. }
  23. @Override
  24. public boolean equals(Object o) {
  25. if (this == o) return true;
  26. if (o == null || getClass() != o.getClass()) return false;
  27. Student student = (Student) o;
  28. if (age != student.age) return false;
  29. return name != null ? name.equals(student.name) : student.name == null;
  30. }
  31. @Override
  32. public int hashCode() {
  33. int result = name != null ? name.hashCode() : 0;
  34. result = 31 * result + age;
  35. return result;
  36. }
  37. @Override
  38. public String toString() {
  39. return "Student{" +
  40. "name='" + name + '\'' +
  41. ", age=" + age +
  42. '}';
  43. }
  44. }
  1. package com.itheima.map_demo.map_test;
  2. import java.util.HashMap;
  3. import java.util.Set;
  4. /*
  5. HashMap类 :
  6. 存储数据,每位学生(姓名,年龄)都有自己的家庭住址。
  7. 学生和地址有对应关系,将学生对象和家庭住址存储到map集合中。学生作为键, 家庭住址作为值。
  8. 要求:学生姓名相同并且年龄相同视为同一名学生,不能重复存储
  9. */
  10. public class HashMapTest {
  11. public static void main(String[] args) {
  12. // 学生作为键, 家庭住址作为值。
  13. HashMap<Student, String> hm = new HashMap<>();
  14. hm.put(new Student("迪丽热巴", 18) , "新疆");
  15. hm.put(new Student("迪丽热巴", 18) , "中国");
  16. Set<Student> set = hm.keySet();
  17. for (Student key : set) {
  18. String value = hm.get(key);
  19. System.out.println(key + "--" + value);
  20. }
  21. }
  22. }

5.7 LinkedHashMap集合

  • LinkedHashMap类 , 在最底层采用的数据结构 : 是链表+哈希表。
  • 特点 :

    • 元素唯一
    • 元素有序
  1. package com.itheima.map_demo.map_test;
  2. import java.util.LinkedHashMap;
  3. import java.util.Set;
  4. /*
  5. LinkedHashMap类 , 在最底层采用的数据结构 : 是链表+哈希表。
  6. 特点 :
  7. 1 元素唯一
  8. 2 有序
  9. 需求 : 创建LinkedHashMap对象 , 添加元素进行验证 元素唯一 , 有序的特点
  10. */
  11. public class LinkedHashMapTest {
  12. public static void main(String[] args) {
  13. // 创建集合对象
  14. LinkedHashMap<Integer, String> linkedHashMap = new LinkedHashMap<>();
  15. linkedHashMap.put(1, "张三");
  16. linkedHashMap.put(1, "李四");
  17. linkedHashMap.put(2, "王五");
  18. linkedHashMap.put(3, "赵六");
  19. System.out.println(linkedHashMap);
  20. }
  21. }

5.8 TreeMap集合

  • TreeMap的底层是红黑树实现的,有排序的能力,键去重。

  • 可以自然排序(键所在的类要实现Comparable)

  • 若自定义类没有自然排序功能,或自然排序功能不满足要求时。可以自定义比较器排序(Comparator)

  1. package com.itheima.map_demo.map_test;
  2. import java.util.TreeMap;
  3. /*
  4. 需求 :
  5. 定义TreeMap集合存储键值对,键使用Integer,值使用String,存储若干键值对,遍历集合观察结果是否有排序。
  6. */
  7. public class TreeMapTest1 {
  8. public static void main(String[] args) {
  9. // 定义TreeMap集合存储键值对,键使用Integer,值使用String
  10. // 创建集合对象
  11. TreeMap<Integer, String> treeMap = new TreeMap<>();
  12. treeMap.put(1, "张三");
  13. treeMap.put(3, "赵六");
  14. treeMap.put(2, "王五");
  15. System.out.println(treeMap);
  16. }
  17. }
  1. package com.itheima.map_demo.map_test;
  2. import java.util.Comparator;
  3. import java.util.TreeMap;
  4. /*
  5. 需求:创建一个TreeMap集合,键是学生对象(Student),值是籍贯(String)。
  6. 学生属性姓名和年龄, 要求按照年龄进行升序排序并遍历
  7. */
  8. public class TreeMapTest2 {
  9. public static void main(String[] args) {
  10. // 学生作为键, 家庭住址作为值。
  11. TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() {
  12. @Override
  13. public int compare(Student o1, Student o2) {
  14. return o1.getAge() - o2.getAge();
  15. }
  16. });
  17. tm.put(new Student("迪丽热巴", 18), "新疆");
  18. tm.put(new Student("迪丽热巴", 16), "中国");
  19. System.out.println(tm);
  20. }
  21. }

6 集合嵌套

6.1 List嵌套List

  1. package com.itheima.Collection_nested_demo;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /*
  5. 使用场景举例:一年级有多个班级,每个班级有多名学生。要求保存每个班级的学生姓名,保存一个年级所有的班级信息
  6. 思路:
  7. 可以使用List集合保存一个班级的学生
  8. 可以使用List集合保存所有班级
  9. 因此我们可以定义集合如下:
  10. 班级:List<String>
  11. 举例 :
  12. List<String> 三年一班 = {迪丽热巴 , 古力娜扎 ,马尔扎哈 ,欧阳娜娜}
  13. List<String> 三年二班 = {李小璐 , 白百何 , 马蓉}
  14. List<String> 三年三班 = {林丹 ,文章, 陈赫}
  15. 年级:List<List<String>>
  16. 举例 :
  17. List<List<String>> 年级 = {三年一班 , 三年二班 , 三年三班}
  18. */
  19. public class Test3 {
  20. public static void main(String[] args) {
  21. List<String> 三年一班 = new ArrayList<>();
  22. 三年一班.add("迪丽热巴");
  23. 三年一班.add("古力娜扎");
  24. 三年一班.add("马尔扎哈");
  25. 三年一班.add("欧阳娜娜");
  26. List<String> 三年二班 = new ArrayList<>();
  27. 三年二班.add("李小璐");
  28. 三年二班.add("白百何");
  29. 三年二班.add("马蓉");
  30. List<String> 三年三班 = new ArrayList<>();
  31. 三年三班.add("林丹");
  32. 三年三班.add("文章");
  33. 三年三班.add("陈赫");
  34. List<List<String>> 年级 = new ArrayList<>();
  35. 年级.add(三年一班);
  36. 年级.add(三年二班);
  37. 年级.add(三年三班);
  38. for (List<String> 班级 : 年级) {
  39. for (String name : 班级) {
  40. System.out.println(name);
  41. }
  42. System.out.println("-----------------");
  43. }
  44. }
  45. }

6.2 List嵌套Map

  1. package com.itheima.Collection_nested_demo;
  2. import java.util.*;
  3. /*
  4. List嵌套Map :
  5. 使用场景举例:一年级有多个班级,每个班级有多名学生。要求保存每个班级的学生姓名,姓名有与之对应的学号,保存一年级所有的班级信息。
  6. 思路:
  7. 1 可以使用Map集合保存一个班级的学生(键是学号,值是名字)
  8. 2 可以使用List集合保存所有班级
  9. 因此我们可以定义集合如下:
  10. 班级:Map<String,String> 键是学号,值是姓名
  11. 举例 :
  12. Map<String,String> 三年一班 = {it001 = 迪丽热巴 , it002 = 古力娜扎 ,it003 = 马尔扎哈 ,it004 = 欧阳娜娜}
  13. Map<String,String> 三年二班 = {it001 = 李小璐 , it002 = 白百何 , it003 = 马蓉}
  14. Map<String,String> 三年三班 = {it001 = 林丹 ,it002 = 文章, it003 = 陈赫}
  15. 年级:List<Map<String,String>>保存每个班级的信息
  16. 举例 :
  17. List<Map<String,String>> 年级 = {三年一班 , 三年二班 , 三年三班}
  18. */
  19. public class Test2 {
  20. public static void main(String[] args) {
  21. Map<String, String> 三年一班 = new HashMap<>();
  22. 三年一班.put("it001", "迪丽热巴");
  23. 三年一班.put("it002", "古力娜扎");
  24. 三年一班.put("it003", "马尔扎哈");
  25. 三年一班.put("it004", "欧阳娜娜");
  26. Map<String, String> 三年二班 = new HashMap<>();
  27. 三年二班.put("it001", "李小璐");
  28. 三年二班.put("it002", "白百何");
  29. 三年二班.put("it003", "马蓉");
  30. Map<String, String> 三年三班 = new HashMap<>();
  31. 三年三班.put("it001", "林丹");
  32. 三年三班.put("it002", "文章");
  33. 三年三班.put("it003", "陈赫");
  34. List<Map<String, String>> 年级 = new ArrayList<>();
  35. 年级.add(三年一班);
  36. 年级.add(三年二班);
  37. 年级.add(三年三班);
  38. for (Map<String, String> 班级 : 年级) {
  39. Set<String> studentId = 班级.keySet();
  40. for (String id : studentId) {
  41. String name = 班级.get(id);
  42. System.out.println(id + "---" + name);
  43. }
  44. System.out.println("=================");
  45. }
  46. }
  47. }

6.3 Map嵌套Map

  1. package com.itheima.Collection_nested_demo;
  2. import java.util.*;
  3. /*
  4. Map嵌套Map
  5. 使用场景举例:一个年级有多个班级,每个班级有多名学生。要求保存每个班级的学生姓名,姓名有与之对应的学号,保存一年级所有的班级信息,班级有与之对应的班级名称。
  6. 思路:
  7. 可以使用Map集合保存一个班级的学生(键是学号,值是名字)
  8. 可以使用Map集合保存所有班级(键是班级名称,值是班级集合信息)
  9. 因此我们可以定义集合如下:
  10. 班级: Map<String,String> 键:学号,值:姓名
  11. 举例 :
  12. Map<String,String> 三年一班 = {it001 = 迪丽热巴 , it002 = 古力娜扎 ,it003 = 马尔扎哈 ,it004 = 欧阳娜娜}
  13. Map<String,String> 三年二班 = {it001 = 李小璐 , it002 = 白百何 , it003 = 马蓉}
  14. Map<String,String> 三年三班 = {it001 = 林丹 ,it002 = 文章, it003 = 陈赫}
  15. 年级: Map<String , Map<String,String>> 键:班级名称,值:具体班级信息
  16. 举例:
  17. Map<String, Map<String,String>> 年级 = {"三年一班" = 三年一班 , "三年二班" = 三年二班 , "三年三班" = 三年三班 }
  18. */
  19. public class Test3 {
  20. public static void main(String[] args) {
  21. Map<String, String> 三年一班 = new HashMap<>();
  22. 三年一班.put("it001", "迪丽热巴");
  23. 三年一班.put("it002", "古力娜扎");
  24. 三年一班.put("it003", "马尔扎哈");
  25. 三年一班.put("it004", "欧阳娜娜");
  26. Map<String, String> 三年二班 = new HashMap<>();
  27. 三年二班.put("it001", "李小璐");
  28. 三年二班.put("it002", "白百何");
  29. 三年二班.put("it003", "马蓉");
  30. Map<String, String> 三年三班 = new HashMap<>();
  31. 三年三班.put("it001", "林丹");
  32. 三年三班.put("it002", "文章");
  33. 三年三班.put("it003", "陈赫");
  34. Map<String, Map<String, String>> 年级 = new HashMap<>();
  35. 年级.put("三年一班", 三年一班);
  36. 年级.put("三年二班", 三年二班);
  37. 年级.put("三年三班", 三年三班);
  38. Set<String> 班级名字集合 = 年级.keySet();
  39. for (String 班级名字 : 班级名字集合) {
  40. Map<String, String> 班级信息 = 年级.get(班级名字);
  41. Set<String> 学生学号 = 班级信息.keySet();
  42. for (String 学号 : 学生学号) {
  43. String 姓名 = 班级信息.get(学号);
  44. System.out.println("班级名字:" + 班级名字 + " ,学号:" + 学号 + " , 名字:" + 姓名);
  45. }
  46. System.out.println("============");
  47. }
  48. }
  49. }

7 斗地主案例

  1. package com.itheima.doudizhu;
  2. import java.util.*;
  3. /*
  4. 按照斗地主的规则,完成洗牌发牌的动作。
  5. 要求完成以下功能:
  6. 准备牌:组装54张扑克牌
  7. 洗牌:54张牌顺序打乱
  8. 发牌:三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。
  9. 看牌:查看三人各自手中的牌(按照牌的大小排序)、底牌
  10. 规则:手中扑克牌从大到小的摆放顺序:大王,小王,2,A,K,Q,J,10,9,8,7,6,5,4,3
  11. */
  12. public class DouDiZhu {
  13. public static void main(String[] args) {
  14. // 准备牌
  15. // 键我牌的序号 , 值为牌面
  16. HashMap<Integer, String> pokers = new HashMap<>();
  17. // 牌的颜色
  18. String[] colors = {"♠", "♥", "♣", "♦"};
  19. String[] numbers = {"2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3"};
  20. int count = 2;
  21. for (String number : numbers) {// 3
  22. for (String color : colors) {
  23. // System.out.println(count + " = " + color + number);
  24. pokers.put(count, color + number);
  25. count++;
  26. }
  27. }
  28. pokers.put(0, "大王");
  29. pokers.put(1, "小王");
  30. System.out.println(pokers);
  31. // 洗牌
  32. Set<Integer> set = pokers.keySet();
  33. // 创建存储编号的list集合
  34. List<Integer> list = new ArrayList<>();// {10 , 6 , 8 , 20 , 22 , 11 ... }
  35. // 把set集合中的元素存储到list集合中
  36. list.addAll(set);
  37. // 打乱集合中编号
  38. Collections.shuffle(list);
  39. System.out.println(list);
  40. // 发牌
  41. TreeSet<Integer> 赌神 = new TreeSet<>();
  42. TreeSet<Integer> 赌圣 = new TreeSet<>();
  43. TreeSet<Integer> 赌侠 = new TreeSet<>();
  44. TreeSet<Integer> 底牌 = new TreeSet<>();
  45. // 遍历牌的编号
  46. for (int i = 0; i < list.size() - 3; i++) {
  47. if (i % 3 == 0) {
  48. 赌神.add(list.get(i));
  49. } else if (i % 3 == 1) {
  50. 赌圣.add(list.get(i));
  51. } else {
  52. 赌侠.add(list.get(i));
  53. }
  54. }
  55. 底牌.add(list.get(51));
  56. 底牌.add(list.get(52));
  57. 底牌.add(list.get(53));
  58. System.out.println("赌神:" + 赌神);
  59. System.out.println("赌圣:" + 赌圣);
  60. System.out.println("赌侠:" + 赌侠);
  61. System.out.println("底牌:" + 底牌);
  62. // 看牌
  63. // 赌神
  64. lookPoker(pokers, 赌神, "赌神: ");
  65. // 赌圣
  66. lookPoker(pokers, 赌圣, "赌圣: ");
  67. // 赌侠
  68. lookPoker(pokers, 赌侠, "赌侠: ");
  69. // 底牌
  70. System.out.print("底牌: ");
  71. for (Integer integer : 底牌) {
  72. String poker = pokers.get(integer);
  73. System.out.print(poker + "\t");
  74. }
  75. }
  76. private static void lookPoker(HashMap<Integer, String> pokers, TreeSet<Integer> 赌神, String s) {
  77. System.out.print(s);
  78. for (Integer integer : 赌神) {
  79. String poker = pokers.get(integer);
  80. System.out.print(poker + "\t");
  81. }
  82. System.out.println();
  83. }
  84. }