Java 中集合

1 - 集合的概述

编程的时候如果需要存储多个数据,使用长度固定的数组格式,不一定能满足我们的需求,为了适应不同长度的数据存储需求,Java 给我们提供了集合,来解决这个问题

集合的特点:存储空间是可变的

  • 单列集合 Collection

    • List 可以重复的:ArrayList、LinkedList …
    • Set 不可重复的:HashSet、TreeSet …
  • 双列集合 MapHashMap、TreeMap …

注:加粗 为 接口、 斜体 为 实现类

2 - ArrayList

  • ArrayList<E>

    • 可以调整大小的数组的实现
    • <E> :一种特殊的数据类型,泛型

2.1 - ArrayList 构造方法和添加成员方法

方法名 说明
public ArrayList<E>() 创建一个新的空集合
public boolean add(E e) 将指定的元素添加到集合当中
public void add(int index, E e) 将指定的元素添加到集合的指定位置当中
package com.mrixe.demo;import java.util.ArrayList;/*** @Program: demo01* @Description: ArrayList 构造方法和添加方法* @Author: ice_wan@msn.cn* @Create: 2020-08-31 20:35*/
public class demo01 {public static void main(String[] args) {// ArrayList<String> list = new ArrayList<String>(); // JDK <= 1.7// 创建一个空的集合,用来存储字符串ArrayList<String> list = new ArrayList<>(); // JDK >= 1.8// 向集合中添加成员list.add("JavaSE");list.add("MySQL");list.add("HTML");list.add("CSS");list.add("JavaScript");list.add("jQuery");// 向指定的位置添加元素list.add(1, "Linux");list.add(7, "Redis");// IndexOutOfBoundsExceptionlist.add(9, "Spring");System.out.println(list);}
}

2.2 - ArrayList 集合中的常用方法

方法名 说明
public boolean remove(Object o) 删除指定的元素,返回是否成功
public E remove(int index) 删除指定索引对应的元素,返回被删除的元素
public E set(int index , E e) 修改指定位置的元素,返回修改的元素(原)
public E get(int index) 获取指定索引位置的元素
public int size() 返回集合中元素的个数
package com.mrixe.demo;import java.util.ArrayList;/*** @Program: Demo02* @Description: 遍历集合* @Author: ice_wan@msn.cn* @Create: 2020-08-31 20:48*/
public class Demo02 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.add("赵六");// for (int i = 0; i < list.size(); i++) {//     System.out.print(list.get(i) + "\t");// }for (String str : list){System.out.print(str + "\t");}}
}
//=========================================
package com.mrixe.demo;import java.util.ArrayList;/*** @Program: Demo03* @Description: 用集合来存储学生类对象* @Author: ice_wan@msn.cn* @Create: 2020-08-31 21:11*/
public class Demo03 {public static void main(String[] args) {ArrayList<Student> stuList = new ArrayList<>();stuList.add(new Student("张三", 18, "男"));stuList.add(new Student("李四", 17, "女"));stuList.add(new Student("王五", 16, "男"));stuList.add(new Student("赵六", 20, "男"));for (Student stu : stuList){System.out.println(stu.getName() + "\t" + stu.getSex() + "\t" + stu.getAge());}}
}
//===============================================
package com.mrixe.demo;import java.util.ArrayList;
import java.util.Scanner;/*** @Program: Demo04* @Description: 通过键盘输入的方式来向集合中存储学生对象* @Author: ice_wan@msn.cn* @Create: 2020-08-31 21:14*/
public class Demo05 {public static void main(String[] args) {ArrayList<Student> stuList = new ArrayList<>();while (true){System.out.print("Please input student name: ");String name = new Scanner(System.in).nextLine(); //需要一个回车if (name.equals("exit"))break;System.out.print("Please input student age: ");int age = new Scanner(System.in).nextInt(); //需要一个整数类型System.out.print("Please input student sex: ");String sex = new Scanner(System.in).nextLine(); //需要一个回车stuList.add(new Student(name, age, sex));}for (Student stu : stuList){System.out.println(stu.getName() + "\t" + stu.getSex() + "\t" + stu.getAge());}}
}
//================================================
package com.mrixe.demo;import java.util.ArrayList;
import java.util.Scanner;/*** @Program: Demo06* @Description: 将输入动作封装成函数 - 把集合作为参数进行传递* @Author: ice_wan@msn.cn* @Create: 2020-08-31 21:31*/
public class Demo06 {public static void main(String[] args) {ArrayList<Student> stuList = new ArrayList<>();while (addStudent(stuList));for (Student stu : stuList){System.out.println(stu.getName() + "\t" + stu.getSex() + "\t" + stu.getAge());}}/*** 输入学员信息并存储到集合当中* @param stuList* @return true:继续输入   false:不再输入*/private static boolean addStudent(ArrayList<Student> stuList) {System.out.println("Please input student name: ");String name = new Scanner(System.in).nextLine();if (name.equals("exit"))return false;System.out.println("Please input student age: ");int age = new Scanner(System.in).nextInt();System.out.println("Please input student sex: ");String sex = new Scanner(System.in).next();return stuList.add(new Student(name, age, sex));}
}

2.3 - 学员信息管理系统

3 - Collection

3.1 - 概述

  • Collection 是单列集合的顶层接口,它表示一组对象,这些对象也称为 Collection 的元素
  • 应用
package com.mrxie;import java.util.ArrayList;
import java.util.Collection;/*** @Program: Demo01* @Description: Collection简单案例* @Author: ice_wan@msn.cn* @Create: 2020-09-06 09:12*/
public class Demo01 {public static void main(String[] args) {// 使用多态的形式,用父类接口存储实现类的对象Collection<String> collection = new ArrayList<>();// 使用 add 方法,向集合中添加成员collection.add("星期天");collection.add(" 一大早 ");collection.add(" 来上课 ");// collection 中有 toString 方法的重写System.out.println(collection);}
}

3.2 - Collection 常用方法

方法名 说明
boolean add(E e) 添加元素
boolean remove(Object o) 删除元素
void clear() 清空集合
boolean contains(Object o) 判断指定的元素是否存在
boolean isEmpty() 判断集合是否为空
int size() 返回集合长度
package com.mrxie;/*** @Program: Demo02* @Description: Collection 常用方法* @Author: ice_wan@msn.cn* @Create: 2020-09-06 09:18*/import java.util.ArrayList;
import java.util.Collection;/*** boolean add(E e)添加元素* boolean remove(Object o)删除元素* void clear()清空集合* boolean contains(Object o)判断指定的元素是否存在* boolean isEmpty()判断集合是否为空* int size()*/
public class Demo02 {public static void main(String[] args) {Collection<String> con = new ArrayList<>();// boolean add(E e)添加元素con.add("AAAAAA");con.add("BBBBBB");con.add("CCCCCC");con.add("DDDDDD");con.add("EEEEEE");// boolean remove(Object o)删除元素// con.remove("AAAAAA");// void clear()清空集合 - 慎用// con.clear();// boolean isEmpty()判断集合是否为空 不是空返回false 空返回true// System.out.println(con.isEmpty());// int size()// System.out.println(con.size());// 遍历for (String str : con){System.out.println(str);}// boolean contains(Object o)判断指定的元素是否存在// System.out.println(con.contains("BBBBBB")); //存在返回true// System.out.println(con.contains("XXXXXX")); //不存在返回false}
}
//============================================================
package com.mrxie;import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;/*** @Program: Demo03* @Description: 模拟文件上传动作(文件名的重复问题处理)* @Author: ice_wan@msn.cn* @Create: 2020-09-06 09:24*/
public class Demo03 {public static void main(String[] args) {Collection<String> fileNames = new ArrayList<>();final String charList = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVFXYX1234567890";final String ext = ".txt";String uploadFile = "";Random ran = new Random();// 模拟服务器中已存在的文件名for (int i = 0; i < 100; i++) {uploadFile = "";for (int j = 0; j < 16; j++) {uploadFile += charList.charAt(ran.nextInt(charList.length()));}uploadFile += ext;if (!fileNames.contains(uploadFile)){fileNames.add(uploadFile);}}// 生成一个可用的文件名,集合中没有的文件名 - 如果生成的文件名存在则重新生成,不存在则退出循环do {uploadFile = "";for (int j = 0; j < 16; j++) {uploadFile += charList.charAt(ran.nextInt(charList.length()));}uploadFile += ext;// 循环体在生成文件名}while (fileNames.contains(uploadFile));    //如果存在则继续循环fileNames.add(uploadFile); //相当于文件上传动作for (String fileName : fileNames){System.out.println(fileName);}System.out.println(fileNames.size());}
}

3.3 - 迭代器

  • Iterator :迭代器,集合的专属遍历方式

    • Iterator<E> iterator() :返回此集合中元素的迭代器,通过 iterator() 方法获得的
  • Interator 中的常用方法

方法名 说明
<E> next() 返回迭代器中的下一个元素
boolean hasNext() 判断迭代其中有没有下一个元素
package com.mrxie;import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;/*** @Program: Demo04* @Description: Collection迭代器遍历* @Author: ice_wan@msn.cn* @Create: 2020-09-06 10:15*/
public class Demo04 {public static void main(String[] args) {Collection<String> collection = new ArrayList<>();collection.add("AAA");collection.add("BBB");collection.add("CCC");// 通过 collection 对象来获取该集合的迭代器对象Iterator<String> it = collection.iterator();// 通过迭代器对象判断该迭代器中有没有下一个元素while (it.hasNext()){// 有就输出这下一个元素System.out.println(it.next());}}
}

4 - List

4.1 - 概述

  • 有序集合(序列),用户可以精确的控制列表中的元素的插入位置,用户可以通过索引来快速的访问集合中的指定元素(访问方式包括读取和写入)
  • List 集合 和 Set 集合不同,List 集合允许有重复的元素出现,而 Set 则不允许重复的值
  • List 集合的特点
    • 有序:存取的顺序是固定的
    • 可重复:元素的值可以相同
package com.mrxie;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;/*** @Program: Demo05* @Description: List 集合的应用* @Author: ice_wan@msn.cn* @Create: 2020-09-06 10:22*/
public class Demo05 {public static void main(String[] args) {// 使用多态来获得实现类对象List<String> list = new ArrayList<>();list.add("AAA");list.add("BBB");list.add("AAA");Iterator<String> it = list.iterator();while (it.hasNext()){System.out.println(it.next());}}
}

4.2 - List 集合中常用方法

方法名 说明
void add(int index, E e) 在集合的指定位置插入成员
E remove(int index) 删除指定位置的元素
E set(int index, E e) 修改指定位置的元素
E get(int index) 获取指定位置的元素
package com.mrxie;import java.util.ArrayList;
import java.util.List;/*** @Program: Demo06* @Description: List 常用方法* @Author: ice_wan@msn.cn* @Create: 2020-09-06 10:28*/
public class Demo06 {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("AAA");list.add("BBB");list.add("CCC");list.add("DDD");list.add(1, "XXX"); // 向指定的位置添加成员System.out.println("删除返回的 - " + list.remove(1));System.out.println("修改之前的 - " + list.set(1, "bbb"));for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}}
}

4.3 - 插入算法(数组)

package com.mrxie;import java.util.Scanner;/*** @Program: Demo07* @Description: 向数组的指定位置插入一个成员* @Author: ice_wan@msn.cn* @Create: 2020-09-06 10:34*/
public class Demo07 {public static void main(String[] args) {// 定义一个数组int[] arr = new int[10];// 初始化数组,少初始化一个元素,为了插入一个新的元素for (int i = 0; i < arr.length - 1; i++) {arr[i] = i + 1;}System.out.print("请输入要插入元素的下标位置: ");int index = new Scanner(System.in).nextInt();System.out.println("请输入要插入的数字:");int num = new Scanner(System.in).nextInt();insert(index, num, arr);// 遍历数组for (int n : arr){System.out.print(n + "\t");}}/*** 将 num 插入到 arr 数组的 index 所在位置* @param index 索引(下标)* @param num   要插入的元素* @param arr   目标数组*/private static void insert(int index, int num, int[] arr) {// 一边移动一边插入,相当于是循环的插入num// for (int i = index; i < arr.length; i++) {//     int t = arr[i];  //将数组重元素保存到临时变量中//     arr[i] = num;    //将要插入的值插入的数组中//     num = t;//     num的值在插入之后就没有用了。但是t的值是有用的,//     将t存储到num里,那么num将会被循环的插入到数组中// }// 先把要插入位置后面的元素都移动完毕for (int i = arr.length - 1; i > index; i--){arr[i] = arr[i - 1];}// 再把要插入的数据插入到指定位置arr[index] = num;}
}

4.4 - 并发性修改异常

package com.mrxie;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;/*** @Program: Demo08* @Description: ConcurrentModificationException - 并发性修改异常* @Author: ice_wan@msn.cn* @Create: 2020-09-06 11:23*/
public class Demo08 {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("JavaSE");list.add("MySQL");list.add("Linux");list.add("Spring");//通过迭代器遍历集合,然后通过集合对象本身去修改集合中的成员个数,那么就可能出现并发性修改异常// Iterator<String> it = list.iterator();//// while (it.hasNext()){//     //在迭代器的内部,针对于集合的元素个数有一个叫做预期迭代个数的固定值//     String str = it.next();//     if (str.equals("MySQL"))//         // list.add("JDBC");   //通过集合本身修改了集合的元素个数//         list.set(1, "JDBC");    //可以修改,只要个数不变即可//     //那么这个时候集合本身的个数和这个预期迭代个数不一致了,这种情况下就会出现并发性修改异常// }// 增强for也不行,使用的也是迭代器机制// for (String str : list){//     if (str.equals("MySQL"))//         list.add("JDBC");// }// 解决办法:不是用迭代器,使用普通for没问题!!!for (int i = 0; i < list.size(); i++) {String str = list.get(i);if (str.equals("MySQL"))list.add("JDBC");}System.out.println(list);}
}

4.5 - ListIterator

  • ListIterator :列表迭代器

    • 通过 List 集合的 listIterator() 方法获取迭代器对象,所以它是 List 集合的专属迭代器
    • 可以迭代任意方向,并且可以在迭代过程中修改 List ,还可以获取当前位置
  • ListIterator 常用方法
方法名 说明
E next() 返回下一个元素
boolean hasNext() 有没有下一个元素
E pervious() 返回上一个元素
boolean hasPervious() 有没有上一个元素
void add(E e) 添加一个元素
package com.mrxie;import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;/*** @Program: Demo09* @Description: 迭代* @Author: ice_wan@msn.cn* @Create: 2020-09-06 11:38*/
public class Demo09 {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("JavaSE");list.add("MySQL");list.add("Linux");list.add("Spring");ListIterator<String> lit = list.listIterator();//从前往后遍历while (lit.hasNext()){System.out.println(lit.next());}System.out.println("===========================");//从后往前遍历while (lit.hasPrevious()){System.out.println(lit.previous());}}
}
//=====================================================
package com.mrxie;import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;/*** @Program: Demo09* @Description: 迭代* @Author: ice_wan@msn.cn* @Create: 2020-09-06 11:38*/
public class Demo10 {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("JavaSE");list.add("MySQL");list.add("Linux");list.add("Spring");ListIterator<String> lit = list.listIterator();//从前往后遍历while (lit.hasNext()){String str = lit.next();if (str.equals("MySQL"))lit.add("JDBC");}System.out.println(list);}
}

4.6 - 数据结构

程序 = 数据结构 + 算法

数据结构是计算机存储、组织数据的多种方式。指的是互相之间存在一种或者多种特定关系的数据元素的集合,通常情况下,通过精心的设计、选择数据的结构会给程序的运行和数据的存储提高效率

4.6.1 - 栈

栈模型:先进后出、后进先出 - 只有一个开口端

  • 栈底元素:最先进入到栈模型的元素
  • 栈顶元素:最后进入到栈模型的元素
  • 进栈/压栈:数据进入栈模型的过程
  • 出栈/弹栈:数据离开栈模型的过程
package com.mrxie.demo02;/*** @Program: Demo01* @Description: 递归简单案例* @Author: ice_wan@msn.cn* @Create: 2020-09-06 14:53*/
public class Demo01 {public static void main(String[] args) {speak(3);}/*** 一个用来说话的函数 说的是数字* @param num 数字*/public static void speak(int num){// 递 - 压栈System.out.println("进栈的时候 num = " + num);if (num > 1)speak(num - 1);// 归 - 弹栈System.out.println("出栈的时候 num = " + num);}
}

4.6.2 - 队列

队列模型:先进先出、后进后出 - 两端都有开口

  • 入队列:数据从后端进入队列的过程
  • 出队列:数据从前端离开队列的过程
package com.mrxie.demo02;/*** @Program: Demo02* @Description: 队列* @Author: ice_wan@msn.cn* @Create: 2020-09-06 15:10*/
public class Demo02 {public static void main(String[] args) {for (int i = 0; i < 10; i++) {speak(i);System.out.println("===============================");}}/**一个在定义了之后没有调用之前是不占用内存的!!!!只有在调用的时候才会进入到内存当中**/private static void speak(int i) {System.out.println("进入队列 i = " + i);System.out.println("随便干了点儿什么,但是没有递归!~");System.out.println("离开队列 i = " + i);}
}

4.6.3 - 数组

相同数据类型变量的不可变长集合 (连续的存储空间) - 查询和修改快、增加和删除慢

  • 查询和修改可以通过索引直接快速定位,读取和写入,效率很高
  • 增加和删除的时候,需要调整其他元素的位置,还要考虑数组的长度问题,效率很低

4.6.4 - 链表

链表模型是一种针对数组而言,增加和删除快,查询和修改慢的数据模型

  • 节点:数据单元
  • 数据域:用来存储实际数据的空间
  • 指针域:用来存储下一个节点地址的空间
package com.mrxie.demo02.link;/*** @Program: ListNode* @Description: 节点* @Author: ice_wan@msn.cn* @Create: 2020-09-06 16:15*/
public class ListNode {int val; //数据域ListNode next = null; //指针域//构造方法,给数据域赋值ListNode(int val){this.val = val;}
}
//===============================================
package com.mrxie.demo02.link;/*** @Program: Demo03* @Description: 单链表* @Author: ice_wan@msn.cn* @Create: 2020-09-06 15:27*/
public class Demo03 {public static void main(String[] args) {// 创建一个头结点,存储一个特殊的值,方便我辨认!~ListNode listHead = new ListNode(9527);// 创建三个节点ListNode l01 = new ListNode(3);ListNode l02 = new ListNode(5);ListNode l03 = new ListNode(7);// 将刚刚创建的三个节点添加到 listHead 为头结点的 链表 当中addNode(listHead, l01);addNode(listHead, l02);addNode(listHead, l03);// 输出链当中的说有节点 - 遍历showListNode(listHead);// 求链表中有效节点的长度System.out.println("链表的长度为: " + getLengthOfListNode(listHead));// 删除一个节点removeNode(listHead, l02);showListNode(listHead);System.out.println("=============================");// 在 l01 后面 添加 l02 节点addNode(listHead, l01, l02);showListNode(listHead);// 修改指定的元素 - 思考完成}/*** 在 listNode 链中的 node01 节点后面 添加 node02 节点* @param listNode  链* @param node01    目标节点位置* @param node02    要插入的节点*/private static void addNode(ListNode listNode, ListNode node01, ListNode node02) {ListNode tmpNode;while (null != listNode.next){tmpNode = listNode.next;if (tmpNode.val == node01.val){node02.next = tmpNode.next;listNode.next.next = node02;break;}listNode = tmpNode;}//课后思考关系!~}/*** 在 listNode 中删除一个 节点* @param listNode  链* @param node      要删除的节点*/private static void removeNode(ListNode listNode, ListNode node) {ListNode tmpNode;//如果当前节点的指针域不是空的,说明当前节点不是尾节点while (null != listNode.next){// 如果你要操作当前这个节点,需要将当前节点的指针域指向的想一个节点作为保存tmpNode = listNode.next;if (node.val == tmpNode.val){listNode.next = tmpNode.next;}listNode = tmpNode;}}/*** 链表的长度* @param listNode 链表的头结点* @return 链表的有效节点长度*/private static int getLengthOfListNode(ListNode listNode) {int len = 0;// 跳过头结点listNode = listNode.next;while (null != listNode){len++;listNode = listNode.next;}return len;}/*** 输出以 listHead 为头结点的 链表 中的数据* @param listNode 头结点*/private static void showListNode(ListNode listNode) {// 跳过头结点,因为头结点中存储了特殊化数据listNode = listNode.next;// 只要不是尾节点那就循环while (null != listNode){// 输出数据域System.out.println(listNode.val);// 后移指针域listNode = listNode.next;}}/*** 向 ListNode 链尾部添加 node 节点* @param listNode  链* @param node      要插入的节点*/public static void addNode(ListNode listNode, ListNode node){// 如果是一个空的链,那么就将此节点赋值给当前的链表作为头结点if (null == listNode)listNode = node;if (null != listNode){// 找到最后一个节点while (listNode.next != null){listNode = listNode.next;}// 将当前要插入的节点放到链尾节点的指针域当中listNode.next = node;}}
}

4.7 - LinkedList

4.7.1 - LiknkedList 中的常用方法

方法名 说明
public void addFirst(E e) 头结点添加
public void addLast(E e) 尾节点添加
public E getFirst() 获取头结点
public E getLast() 获取尾节点
public E removeFirst() 删除头结点
public E removeLast() 删除尾节点
package com.mrxie;import java.util.LinkedList;/*** @Program: Demo01* @Description: LinkedList 案例* @Author: ice_wan@msn.cn* @Create: 2020-09-07 20:20*/
public class Demo01 {public static void main(String[] args) {LinkedList<String> list = new LinkedList<>();list.add("AAAA");   //0list.add("BBBB");   //1list.add("CCCC");   //2list.set(2, "bbbb");    //直接用set修改即可System.out.println(list);list.addFirst("1111");list.addLast("9999");System.out.println(list);System.out.println(list.getFirst());System.out.println(list.getLast());System.out.println(list.removeFirst());System.out.println(list.removeLast());System.out.println(list);}
}

5 - Set

5.1 - 概述

  • 概述:Set 同样也是一个接口,与 List 类似,通需要通过实现类来进行操作

  • Set 特点:

    • 不能包含重复的值
    • 没有带索引 的方法,所以不能使用下标相关操作,普通的 for 循环也不能对其进行遍历
package com.mrxie;import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;/*** @Program: Demo02* @Description: Set 简单案例* @Author: ice_wan@msn.cn* @Create: 2020-09-07 20:32*/
public class Demo02 {public static void main(String[] args) {Set<String> set = new HashSet<>();set.add("111");set.add("222");set.add("333");// set集合中不允许出现重复的值set.add("333");System.out.println(set);System.out.println("=================");for (String str : set){System.out.println(str);}System.out.println("=================");Iterator<String> it = set.iterator();while (it.hasNext()){System.out.println(it.next());}}
}

5.2 - 哈希值

哈希值就是 JDK 根据对象的地址 或者 字符串的 或者 数值 计算出来的一个 int 类型的数值

Object 对象都会有一个 hashCode(), hashCode 方法用来好获取一个对象的哈希值

  • 哈希值的特点

    • 同一个对象多次调用 hashCode 方法,得到的返回值是相同的
    • 默认情况下,不同对象的哈希值是不同的

5.3 - HashSet

  • HashSet 特点

    • 底层数据结构是 “哈希表”
    • 对于集合的迭代循序(读写顺序)不保证
    • 没有索引的概念
    • 不包含重复的值
  • 去重原理

    • 先对比 hashcode 的值,如果值相同的话,在对比 equals 的内容,有任意一个不相同则视为不同对象

      因为 hashcode 相同的值不一定就是同一个对象,而 hashcode 不同的值就一定不是同一个对象

5.4 - 哈希表

数组 + 链表

哈希值会被 % 16(这个哈希表中一共有16个元素,下标从 0-15 )

5.5 - 去重案例

package com.mrxie;import java.util.Objects;/*** @Program: Person* @Description: 人类* @Author: ice_wan@msn.cn* @Create: 2020-09-07 21:17*/
public class Person {private String name;private String sex;private int age;public Person() {}public Person(String name, String sex, int age) {this.name = name;this.sex = sex;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", sex='" + sex + '\'' +", age=" + age +'}';}//重写了 equlas 和 hashCode方法@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return age == person.age &&Objects.equals(name, person.name) &&Objects.equals(sex, person.sex);}@Overridepublic int hashCode() {return Objects.hash(name, sex, age);}
}
//======================================================
package com.mrxie;import java.util.HashSet;/*** @Program: Demo05* @Description: 去重* @Author: ice_wan@msn.cn* @Create: 2020-09-07 21:17*/
public class Demo05 {public static void main(String[] args) {HashSet<Person> phs = new HashSet<>();phs.add(new Person("刘德华", "男", 55));phs.add(new Person("谭咏麟", "男", 54));phs.add(new Person("林子祥", "男", 23));phs.add(new Person("许冠杰", "男", 34));// 再插入一个刘德华phs.add(new Person("刘德华", "男", 55));for (Person p : phs){System.out.println(p);}}
}

5.6 - LinkedHashSet

  • LinkedHashSet 特点

    • 它是哈希表 和 链表实现的 Set 几口,具有可预测的迭代顺序(读写顺序一致)
    • 顺序是由链表来保证的
    • 由 HashSet 来保证元素的唯一性,由链表来保证元素的迭代顺序
package com.mrxie;import java.util.HashSet;
import java.util.LinkedHashSet;/*** @Program: Demo05* @Description: 去重* @Author: ice_wan@msn.cn* @Create: 2020-09-07 21:17*/
public class Demo06 {public static void main(String[] args) {LinkedHashSet<Person> phs = new LinkedHashSet<>();phs.add(new Person("刘德华", "男", 55));phs.add(new Person("谭咏麟", "男", 54));phs.add(new Person("林子祥", "男", 23));phs.add(new Person("许冠杰", "男", 34));for (Person p : phs){System.out.println(p);}}
}

5.7 - TreeSet

  • 特点

    • 有序(指的是规则顺序,不是读写顺序)
    • 规则通过构造方法来界定
      • TreeSet():自然排序规则(升序排序)
      • TreeSet(Comparator c):自定义排序规则(通过比较器实现)
package com.mrxie;import java.util.TreeSet;/*** @Program: Demo07* @Description: TreeSet 自然排序规则(升序)* @Author: ice_wan@msn.cn* @Create: 2020-09-07 21:53*/
public class Demo07 {public static void main(String[] args) {TreeSet<Integer> ts = new TreeSet<>();ts.add(90);ts.add(19);ts.add(41);ts.add(153);ts.add(61);ts.add(14);ts.add(111);ts.add(144);for (Integer i : ts){System.out.println(i);}}
}
//==============================================自定义排序规则 - 接口实现
package com.mrxie;/*** @Program: Student* @Description: 学生类* @Author: ice_wan@msn.cn* @Create: 2020-09-07 21:57*/
public class Student /*implements Comparable<Student>*/{private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", 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;}/*** 排序规则* @param stu 比较的下一个对象* @return 0相等(不插入) >0大于(插入到后面) <0小于(插入到前面)*/// @Override// public int compareTo(Student stu) {//     //按照年龄进行排序,如果年龄相同按照姓名进行排序//     int res =  this.age - stu.getAge();//     if (0 == res){//         return this.getName().compareTo(stu.getName());//     }//     return res;// }
}
//==============================================自定义排序规则 - 匿名内部类
package com.mrxie;import java.util.Comparator;
import java.util.TreeSet;/*** @Program: Demo08* @Description: 接口实现自定义排序规则* @Author: ice_wan@msn.cn* @Create: 2020-09-07 21:57*/
public class Demo08 {public static void main(String[] args) {TreeSet<Student> stus = new TreeSet<>(new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {int res = o1.getAge() - o2.getAge();return (0 == res ? o1.getName().compareTo(o2.getName()) : res);}});stus.add(new Student("Ice", 17));stus.add(new Student("Tom", 15));stus.add(new Student("Jack", 14));stus.add(new Student("Lucy", 15));stus.add(new Student("Andy", 19));for (Student stu : stus){System.out.println(stu);}}
}
  • 35 选 7
package com.mrxie.demo01;import java.lang.reflect.Array;
import java.util.*;/*** @Program: Demo01* @Description: 35 选 7 - 集合方式实现* @Author: ice_wan@msn.cn* @Create: 2020-09-08 20:08*/
public class Demo01 {public static void main(String[] args) {// List 集合实现// listDemo();// Set  集合实现// setDemo();// 数组 实现arrayDemo();}/*** 数组 实现 35 选 7 - 面向过程!!!*/private static void arrayDemo() {int[] arr = new int[7];Random ran = new Random();int num = 0;System.out.println("请输入要生成多少注:");int count = new Scanner(System.in).nextInt();for (int k = 0; k < count; k++) {//外循环控制的是一共要生成多少个号码,为数组的长度for (int i = 0; i < 7; i++) {//内循环的循环变量,因为在外循环中要访问它的值所以拿到外面来定义int j = 0;//生成一个随机值num = ran.nextInt(35) + 1;//去重逻辑,要拿刚生成的随机是和之前已经存在在数组里面的元素一一做对比for (j = 0; j < i; j++) {//比较当前生成的这个随机值和数组中已存在的值是否相等,如果相等就不用再往下比了if (num == arr[j]){break;  //不用再往下比了}}//=================//这个j相当于是一个标签,通过j的值我们可以推测出结论//以上去重逻辑循环中,退出循环只有两种可能//第一种:执行到break退出//如果执行到break了,说明循环条件一定的成立的,否则不可能执行到break//所以此时j的值一定是小于i的!!!,那么换句话说,当j<i的时候就说明找到重复的值了//第二种:没执行到break退出//如果没有执行到break,那就说明循环是因为循环条件不成立了所以退出了循环。//那么循环条件是 j 小于 i,那么 他的对立区间是 j 不小于 i, j >= i//换句话说,当 j >= i 的时候说明没有执行到 break,也就是没有找到相同的值if (j >= i){// 那就把这个值放到数组里面arr[i] = num;}else { // 说明是通过 break 退出的// 在这里-- 然后外循环再++, i 的值 相当于没变,下次再生成重新判断i--;}}System.out.println(Arrays.toString(arr));}}/*** Set 集合实现 35 选 7 - 面向对象!!!*/private static void setDemo() {TreeSet<Integer> set = new TreeSet<>();Random ran = new Random();System.out.println("请输入要生成多少注:");int count = new Scanner(System.in).nextInt();for (int i = 0; i < count; i++) {while (set.size() < 7) {set.add(ran.nextInt(35) + 1);}System.out.println(set);set.clear();}}/*** List 集合实现 35 选 7*/private static void listDemo() {ArrayList<Integer> list = new ArrayList<>();Random ran = new Random();System.out.println("请输入要生成多少注:");int count = new Scanner(System.in).nextInt();for (int i = 0; i < count; i++) {// 生成第一个随机值int num = ran.nextInt(35) + 1;// 集合的长度控制在7个元素while (list.size() < 7){// 如果集合中num不存在则将生成的随机值添加到集合当中if (!list.contains(num))list.add(num);//生成新的随机值num = ran.nextInt(35) + 1;}// 输出集合System.out.println(list);// 清空原有的号码集合list.clear();}}
}

6 - 泛型

JKD5 以后才引入的新特性。泛型是在编译阶段针对类型的安全监测机制

泛型类、泛型方法、泛型接口

6.1 - 泛型的定义格式

  • <类型>:指定一种类型的格式,这里的类型可以看做是一个参数
  • <类型1, 类型2 ...>:指定多种类型的格式,多种类型之间使用逗号分隔

6.2 - 好处

  • 把运行使其可能出现的问题提到了编译期间
  • 避免强制类型转换

6.3 - 泛型类

  • 泛型定义格式

    • 格式:修饰符 class 类名<引用数据类型>{}
    • 范例:public class Generic<T>{}

    T 表示的是泛型标识符,这个标识符可以是任意的字符,常见的有 E / K / T / V

package com.mrxie.demo02;/*** @Program: Generic* @Description: 泛型类* @Author: ice_wan@msn.cn* @Create: 2020-09-08 21:36*/
public class Generic<T> {private T t;public Generic() {}public Generic(T t) {this.t = t;}public T getT() {return t;}public void setT(T t) {this.t = t;}
}
//===========================================
package com.mrxie.demo02;/*** @Program: Student* @Description: 学生类* @Author: ice_wan@msn.cn* @Create: 2020-09-08 21:37*/
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;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
//=================================================
package com.mrxie.demo02;/*** @Program: GenericDemo* @Description: 测试类* @Author: ice_wan@msn.cn* @Create: 2020-09-08 21:38*/
public class GenericDemo {public static void main(String[] args) {Generic<String> strG = new Generic<String>("我是个字符串");System.out.println(strG.getT());strG.setT("我是被修改后的字符串");System.out.println(strG.getT());Generic<Integer> intG = new Generic<>(1314);System.out.println(intG.getT() + 1);intG.setT(9527);System.out.println(intG.getT() + 1);Generic<Student> stuG = new Generic<>(new Student("张国荣", 12));System.out.println(stuG.getT());stuG.setT(new Student("柯受良", 14));System.out.println(stuG.getT());}
}

6.4 - 泛型方法

  • 泛型方法定义格式

    • 格式:修饰符 <类型> 返回值类型 方法名(类型名 变量名){}
    • 范例:public <T> void fun(T t){}
package com.mrxie.demo03;/*** @Program: Generic* @Description: 泛型方法* @Author: ice_wan@msn.cn* @Create: 2020-09-08 21:56*/
public class Generic {//泛型方法public <T> void show(T t){System.out.println(t);}//静态泛型方法public static <T> void display(T t){System.out.println(t);}
}
// public class Generic<T> {//     public void show(T t){//         System.out.println(t);
//     }
// }
// public class Generic {//     public void show(String str) {//         System.out.println(str);
//     }
//
//     public void show(boolean b) {//         System.out.println(b);
//     }
//
//     public void show(int i) {//         System.out.println(i);
//     }
//
//     public void show(double v) {//         System.out.println(v);
//     }
// }
//=======================================================
package com.mrxie.demo03;/*** @Program: GenericDemo* @Description: 测试类* @Author: ice_wan@msn.cn* @Create: 2020-09-08 21:59*/
public class GenericDemo {public static void main(String[] args) {Generic g = new Generic();g.show("字符串");g.show(true);g.show(1314);g.show(3.141596);//静态方法调用Generic.display("字符串");Generic.display(true);Generic.display(1314);Generic.display(3.141596);// Generic<String> strG = new Generic<>();// strG.show("字符串");// Generic<Integer> intG = new Generic<>();// intG.show(1314);//...}
}

6.5 - 泛型接口

  • 泛型接口的定义格式

    • 格式:修饰符 interface 接口名<引用数据类型>{}
    • 范例:public interface Generic<T>{}
package com.mrxie.demo04;/*** @Program: Generic* @Description: 泛型接口* @Author: ice_wan@msn.cn* @Create: 2020-09-08 22:10*/
public interface Generic<T> {void show(T t);
}
//============================================
package com.mrxie.demo04;/*** @Program: GenericImpl* @Description: 实现类* @Author: ice_wan@msn.cn* @Create: 2020-09-08 22:11*/
public class GenericImpl<T> implements Generic<T> {@Overridepublic void show(T t) {System.out.println(t);}
}
//=============================================
package com.mrxie.demo04;/*** @Program: GenericDemo* @Description: 测试类* @Author: ice_wan@msn.cn* @Create: 2020-09-08 22:16*/
public class GenericDemo {public static void main(String[] args) {GenericImpl<String> g01 = new GenericImpl<>();g01.show("宋江");//注意:使用内部类实现泛型接口的时候,等号两边都需要邪数据类型!~// Generic<Integer> g02 = new Generic<Integer>() {//     @Override//     public void show(Integer integer) {//         System.out.println("Integer : " + integer);//     }// };// g02.show(9527);new Generic<Integer>() {@Overridepublic void show(Integer integer) {System.out.println("Integer : " + integer);}}.show(9527);}
}

6.6 - 类型通配符

通过通配符可以限制类型的范围

  • 类型通配符 <?>

  • 上限:<? extends 类型>List<? extends Number> - 类型必须是 Number 或 其子类

  • 下限:<? super 类型>List<? super Number> - 类型必须是 Number 或 其父类

package com.mrxie.demo05;import java.util.ArrayList;
import java.util.List;/*** @Program: demo* @Description: 泛型通配符* @Author: ice_wan@msn.cn* @Create: 2020-09-08 22:27*/
public class Demo {public static void main(String[] args) {List<?> list01 = new ArrayList<Object>();List<?> list02 = new ArrayList<String>();List<?> list03 = new ArrayList<Integer>();List<?> list04 = new ArrayList<Float>();List<?> list05 = new ArrayList<Boolean>();List<? extends Number> list06 = new ArrayList<Number>();List<? extends Number> list07 = new ArrayList<Integer>();// List<? extends Number> list08 = new ArrayList<Object>();//超范围List<? super Number> list09 = new ArrayList<Object>();List<? super Number> list10 = new ArrayList<Number>();// List<? super Number> list11 = new ArrayList<Float>();//超范围}
}

6.6 - 可变参数

参数的个数可以发生变化的方法的定义格式

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

范例:public static int sum(int ... a){}

如果可变长参数和普通参数连用,需要将可变长置于形参列表的最后

package com.mrxie.demo;/*** @Program: Demo01* @Description: 可变参数* @Author: ice_wan@msn.cn* @Create: 2020-09-10 20:21*/
public class Demo01 {public static void main(String[] args) {System.out.println(mySum(1,2));System.out.println(mySum(1,2, 3));System.out.println(mySum(1,2, 3, 4));// System.out.println(mySum(1,2, 3, 4));// System.out.println(mySum(1,mySum(1,2, 3, 4)));}public static int mySum(int num, int ... arr){System.out.println("num = " + num);int sum = 0;for (int i : arr){sum += i;}return sum;}// private static int mySum(int i, int i1, int i2, int i3) {//     return i + i1 + i2 + i3;// }//// private static int mySum(int i, int i1, int i2) {//     return i + i1 + i2;// }//// private static int mySum(int i, int i1) {//     return i + i1;// }
}

7 - Map

7.1 - Map 概述

  • interface Map<K, V>:K(Key):键的类型 V(Value):值的类型
  • 将键映射到值的对象;其中键不允许重复;每个键可以映射到最多一个值
  • 范例:学生的学号和姓名
学号(Key) 姓名(Vaule)
ID0001 张三
ID0002 李四
ID0003 张三
ID0004 李四
  • 案例
package com.mrxie.demo02;import java.util.HashMap;
import java.util.Map;/*** @Program: Demo01* @Description: Map集合* @Author: ice_wan@msn.cn* @Create: 2020-09-10 20:56*/
public class Demo01 {public static void main(String[] args) {// 通过实现类对象实例化 Map 集合Map<String, String> map = new HashMap<>();// 添加成员 - 当key不存在的时候是向集合中添加成员map.put("ID0001", "张三");map.put("ID0002", "李四");map.put("ID0003", "张三");map.put("ID0004", "王五");// 如果使用put方法来设置成员,当key存在的时候功能是修改key对应的valuemap.put("ID0003", "张三丰");// 输出Map集合System.out.println(map);}
}

7.2 - 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() 返回集合长度
package com.mrxie.demo02;import java.util.HashMap;
import java.util.Map;/*** @Program: Demo02* @Description: Map 常用方法* @Author: ice_wan@msn.cn* @Create: 2020-09-10 21:06*/
public class Demo02 {public static void main(String[] args) {// 通过实现类对象实例化 Map 集合Map<String, String> map = new HashMap<>();// 添加成员 - 当key不存在的时候是向集合中添加成员map.put("ID0001", "张三");map.put("ID0002", "李四");map.put("ID0003", "张三");map.put("ID0004", "王五");// 删除学员并返回删除的valueSystem.out.println(map.remove("ID0001"));// 如果删除失败,返回null(没有对应的key)System.out.println(map.remove("ID0123"));// 清空集合// map.clear();// 判断键或者值是否存在System.out.println(map.containsKey("ID0003"));  //trueSystem.out.println(map.containsKey("ID0033"));  //falseSystem.out.println(map.containsValue("王五"));    //trueSystem.out.println(map.containsValue("赵四"));    //falseSystem.out.println(map.isEmpty());  // falseSystem.out.println(map.size());     // 3// 输出学员System.out.println(map);}
}

7.3 - Map 获取功能

方法名 说明
V get(Object Key) 根据键获取值
Set<Key> keySet() 获取所有键的Set集合
Collection<Value> values() 获取所有值的Collection集合
Set<Map.Entry<K, V>> entrySet() 获取所有键值对的集合
package com.mrxie.demo02;import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*** @Program: Demo03* @Description: Map 集合中的获取功能* @Author: ice_wan@msn.cn* @Create: 2020-09-10 21:14*/
public class Demo03 {public static void main(String[] args) {// 通过实现类对象实例化 Map 集合Map<String, String> map = new HashMap<>();// 添加成员 - 当key不存在的时候是向集合中添加成员map.put("ID0001", "张三丰");map.put("ID0002", "李四");map.put("ID0003", "张三");map.put("ID0004", "王五");System.out.println(map.get("ID0001"));  //如果成功获取到值System.out.println(map.get("ID0111"));  //如果失败获取到nullSystem.out.println("通过键的集合遍历所有键的值=============");Set<String> keySet = map.keySet();System.out.println(keySet);for (String key : keySet){System.out.println(key);}System.out.println("通过值的集合遍历所有的值================");Collection<String> values = map.values();System.out.println(values);for (String value : values){System.out.println(value);}//很少直接通过值的集合去访问值System.out.println("通过所有键的集合来遍历键对应的值===========");for (String key : keySet){System.out.println(map.get(key));}}
}
  • 遍历集合
package com.mrxie.demo02;import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*** @Program: Demo03* @Description: Map 集合中的获取功能* @Author: ice_wan@msn.cn* @Create: 2020-09-10 21:14*/
public class Demo04 {public static void main(String[] args) {// 通过实现类对象实例化 Map 集合Map<String, String> map = new HashMap<>();// 添加成员 - 当key不存在的时候是向集合中添加成员map.put("ID0001", "张三丰");map.put("ID0002", "李四");map.put("ID0003", "张三");map.put("ID0004", "王五");// 通过键的集合遍历所有键的值Set<String> keySet = map.keySet();// 通过所有键的集合来遍历键对应的值for (String key : keySet){System.out.println(key + " <==> " + map.get(key));}System.out.println("通过键值对方式遍历=========================");// 直接获取键值对Set<Map.Entry<String, String>> entrySet = map.entrySet();for (Map.Entry<String, String> o : entrySet){System.out.println(o.getKey() + " <==> " + o.getValue());}}
}
  • 通过 Map 集合存储学生对象
package com.mrxie.demo02;import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*** @Program: Demo05* @Description: 存储学生对象* @Author: ice_wan@msn.cn* @Create: 2020-09-10 21:27*/
public class Demo05 {public static void main(String[] args) {HashMap<String, Student> stuHm = new HashMap<>();stuHm.put("STU0001", new Student("张三", 19));stuHm.put("STU0002", new Student("李四", 29));stuHm.put("STU0003", new Student("王五", 39));stuHm.put("STU0004", new Student("赵六", 149));stuHm.put("STU0005", new Student("田七", 159));// 通过键集合遍历Set<String> keySet = stuHm.keySet();for (String key : keySet){Student stu = stuHm.get(key);System.out.println(key + " <==> " + stu.getName() + " : " + stu.getAge());}System.out.println("=======================");// 通过键值对遍历Set<Map.Entry<String, Student>> entrySet = stuHm.entrySet();for (Map.Entry<String, Student> o : entrySet){String key = o.getKey();Student stu = o.getValue();System.out.println(key + " <==> " + stu.getName() + " : " + stu.getAge());}}
}

7.4 - 嵌套使用

  • ArrayList 集合中存储 HashMap 集合
package com.mrxie.demo02;import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*** @Program: Demo06* @Description: ArrayList 存储 HashMap 集合* @Author: ice_wan@msn.cn* @Create: 2020-09-10 21:58*/
public class Demo06 {public static void main(String[] args) {ArrayList<HashMap<String, String>> arrayList = new ArrayList<>();HashMap<String, String> hm01 = new HashMap<>();hm01.put("玉帝", "王母");hm01.put("雷公", "电母");HashMap<String, String> hm02 = new HashMap<>();hm02.put("老王", "王妈");hm02.put("老李", "李婶");HashMap<String, String> hm03 = new HashMap<>();hm03.put("郭德纲", "于谦");hm03.put("岳云鹏", "孙悦");// 将三个存储到 list 集合当中arrayList.add(hm01);arrayList.add(hm02);arrayList.add(hm03);// 遍历1for (HashMap<String, String> hm : arrayList){Set<String> keySet = hm.keySet();for (String key : keySet){String value = hm.get(key);System.out.printf("%s \t %s\n", key, value);}}System.out.println("=========================");// 遍历2for (HashMap<String, String> hm : arrayList){Set<Map.Entry<String, String>> entrySet = hm.entrySet();for (Map.Entry<String, String> o : entrySet){String key = o.getKey();String value = o.getValue();System.out.printf("%s \t %s\n", key, value);}}}
}
  • HashMap 集合中存储 ArrayList 集合
package com.mrxie.demo02;import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*** @Program: Demo07* @Description: HashMap 嵌套 ArrayList* @Author: ice_wan@msn.cn* @Create: 2020-09-10 22:17*/
public class Demo07 {public static void main(String[] args) {HashMap<String, ArrayList<String>> hm = new HashMap<>();ArrayList<String> list01 = new ArrayList<>();list01.add("林子祥");list01.add("周润发");hm.put("港台大咖", list01);ArrayList<String> list02 = new ArrayList<>();list02.add("郭德纲");list02.add("于谦");hm.put("相声名家", list02);ArrayList<String> list03 = new ArrayList<>();list03.add("刘翔");list03.add("林丹");hm.put("奥运冠军", list03);// 遍历// 先得到集合中所有的键Set<String> keySet = hm.keySet();// 遍历所有的键for (String key : keySet){// 先输出键System.out.println(key + " ========");// 通过键获取到值,因为值是arrayList类型,所以仍然需要遍历ArrayList<String> value = hm.get(key);// 遍历list集合for (String name : value){System.out.println("\t" + name);}}System.out.println("================================");// 一次性获取键值对集合Set<Map.Entry<String, ArrayList<String>>> entrySet = hm.entrySet();// 遍历键值对结合for (Map.Entry<String, ArrayList<String>> o : entrySet){// 获取键并输出System.out.println(o.getKey() + " ======");// 获取值,因为值也是个集合,所以需要二次遍历ArrayList<String> value = o.getValue();for (String name : value){System.out.println("\t" + name);}}}
}
  • 统计键盘输入的字符串中字符出现的数量
package com.mrixe.demo;import java.util.Scanner;
import java.util.TreeMap;
import java.util.zip.CheckedOutputStream;/*** @Program: Demo01* @Description: 统计键盘输入的字符串中字符出现的数量* @Author: ice_wan@msn.cn* @Create: 2020-09-11 20:12*/
public class Demo01 {public static void main(String[] args) {// * 1 - 先获取一个字符串System.out.println("Please input a string : ");String line = new Scanner(System.in).nextLine();// * 2 - 选择一个适当的集合有序 TreeMap (用Key来存储字符,用value来存储出现的次数)TreeMap<Character, Integer> tm = new TreeMap<>();// * 3 - 遍历这个字符串,取到字符串中的每个字符,如果不存在就添加到集合中,如果存在就累加出现的次数for (int i = 0; i < line.length(); i++) {char key = line.charAt(i);      // 用字符作为keyInteger count = tm.get(key);    // 给key对应的计数变量赋值if (null == count){         //如果是空说明第一次统计这个字符,所以赋值为1tm.put(key, 1);}else {                     //不是空说明之前统计过这个字符tm.put(key, ++count);   //先++count的值做一次递增,然后在给key当中的value重新赋值}}// * 4 - 输出我们的统计结果for (char key : tm.keySet()){System.out.println(key + " : 出现了 " + tm.get(key) + " 次");}}
}

8 - Collections

方法名 说明
public static <T extends Comparable<? super T>> void sort(List<T> list) 排序
public static void reverse(List<?> list) 逆序
public static void shuffle(List<?> list) 洗牌
package com.mrixe.demo;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;/*** @Program: Demo02* @Description: Collections* @Author: ice_wan@msn.cn* @Create: 2020-09-11 20:42*/
public class Demo02 {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(55);list.add(88);list.add(66);list.add(44);list.add(33);list.add(99);list.add(77);// Collections.sort(list); // 自然规则排序// Collections.sort(list, new Comparator<Integer>() {//     @Override//     public int compare(Integer o1, Integer o2) {//         return o2 - o1;//     }// }); // 自定义排序规则// Collections.reverse(list);  // 逆序排列Collections.shuffle(list);System.out.println(list);}
}
  • 模拟斗地主发牌
package com.mrixe.demo;import java.util.*;/*** @Program: Demo03* @Description: 模拟斗地主发牌* @Author: ice_wan@msn.cn* @Create: 2020-09-11 20:48*/
public class Demo03 {public static void main(String[] args) {// 定义一个 HashMap 集合用于存储扑克牌HashMap<Integer, String> card = new HashMap<>();// 定义一个 ArrayList 集合用于存储扑克牌的索引ArrayList<Integer> keyList = new ArrayList<>();// 生成扑克牌,将扑克牌放到扑克盒里String[] colors = {"♥", "♠", "♦", "♣"};String[] nums = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};// 将点数和花色拼接成扑克牌并放到扑克盒里int index = 0;  // 定义一个索引for (String num : nums) {    // 遍历点数for (String color : colors) {    // 遍历花色card.put(index, color + num);keyList.add(index++);   // ++后置,先取值再++}}card.put(index, "大王");keyList.add(index++);card.put(index, "小王");keyList.add(index);// 遍历测试扑克生成// Set<Map.Entry<Integer, String>> entrySet = card.entrySet();// for (Map.Entry<Integer, String> o : entrySet){//     System.out.println(o.getValue());// }// 洗牌Collections.shuffle(keyList);// 定义玩家和底牌TreeSet<Integer> player01 = new TreeSet<>();TreeSet<Integer> player02 = new TreeSet<>();TreeSet<Integer> player03 = new TreeSet<>();TreeSet<Integer> lastThreeCard = new TreeSet<>();// 发牌for (int i = 0; i < keyList.size(); i++) {if (i >= keyList.size() - 3) {    // 最后三张发给底牌lastThreeCard.add(keyList.get(i));} else {switch (i % 3) {case 0:player01.add(keyList.get(i));break;case 1:player02.add(keyList.get(i));break;case 2:player03.add(keyList.get(i));break;}}}// 看牌showCard("兰林祥", player01, card);showCard("董斌", player02, card);showCard("罗宇飞", player03, card);showCard("底牌", lastThreeCard, card);}private static void showCard(String name, TreeSet<Integer> ts, HashMap<Integer, String> card) {System.out.println(name + " : ");for (Integer key : ts) {System.out.print(card.get(key) + " ");}System.out.println("\n==============================");}
}

9 - Properties

直接把 Properties 当做 Map 集合来使用就行了, 操作流更方便

package com.mrixe.demo;import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;/*** @Program: Demo04* @Description: Properites 案例* @Author: ice_wan@msn.cn* @Create: 2020-09-11 21:41*/
public class Demo04 {public static void main(String[] args) {// 获得一个 类似 Map 集合的 Properties 对象Properties prop = new Properties();// 存储元素prop.put("东邪", "黄固");prop.put("西毒", "欧阳锋");prop.put("南帝", "段智兴");prop.put("北丐", "洪七公");prop.put("中神通", "王重阳");//遍历集合// Set<Object> keySet = prop.keySet();// for (Object key : keySet){//     System.out.println(key + " : " + prop.get(key));// }Set<Map.Entry<Object, Object>> entrySet = prop.entrySet();for (Map.Entry<Object, Object> o : entrySet){System.out.println(o.getKey() + " <==> " + o.getValue());}}
}
  • 使用 Properties 的特有方法实现存取
package com.mrixe.demo;import javax.swing.*;
import java.util.Properties;
import java.util.Set;/*** @Program: Demo05* @Description: Properties 特有方法实现存取* @Author: ice_wan@msn.cn* @Create: 2020-09-11 21:48*/
public class Demo05 {public static void main(String[] args) {Properties prop = new Properties();prop.setProperty("东邪", "黄蓉");prop.setProperty("西毒", "欧阳克");prop.setProperty("南帝", "段正淳");prop.setProperty("北丐", "郭靖");prop.setProperty("老顽童", "周伯通");// Set<Object> keySet = prop.keySet();// for (Object key : keySet){//     System.out.println(key + " -- " + prop.getProperty(key.toString()));// }// stringPropertyNames : 得到key的String类型的set集合// getProperty : 通过 String 类型的 key 得到 到 valueSet<String> names = prop.stringPropertyNames();for (String key : names){System.out.println(key + " ^_< " + prop.getProperty(key));}}
}
  • 利用 Properties 实现 IO 流的存储
package com.mrixe.demo;import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;/*** @Program: Demo06* @Description: Properties IO* @Author: ice_wan@msn.cn* @Create: 2020-09-11 21:58*/
public class Demo06 {public static void main(String[] args) throws IOException {// 写入方法// myStore();// 读取方法myLoad();}private static void myLoad() throws IOException {// 获取对象Properties prop = new Properties();// 获取输入流对象FileReader fr = new FileReader("./PropertiesTest.txt");// 读取键值对到 prop 中prop.load(fr);// 关闭输入流fr.close();// 遍历集合Set<Object> keySet = prop.keySet();for (Object key : keySet){System.out.println(key + " \t<==>\t" + prop.get(key));}}/*** 写入操作* @throws IOException*/private static void myStore() throws IOException {Properties prop = new Properties();prop.put("东邪", "黄固");prop.put("西毒", "欧阳锋");prop.put("南帝", "段智兴");prop.put("北丐", "洪七公");prop.put("中神通", "王重阳");FileWriter fw = new FileWriter("./PropertiesTest.txt");// prop.store(fw, "射雕英雄传");    //字符编码// prop.store(fw, "Ice Alter!~");  //原样写入prop.store(fw, null);   //啥也没有fw.close();}
}

10 - 小结

  • 集合分为单列集合:Collection 和 双列集合:Map
  • Collection: List/Set
    • List: ArrayList / LinkedList …

      • ArrayList : 底层是数组,所以查询和修改快,删除和添加慢
      • LinkedList : 底层是链表,所以查询和修改慢,删除和添加快
    • Set: HashSet / TreeSet … (没有索引)
      • HashSet : 底层是哈希表,读写无序
      • LinkedHashSet : 底层是链表和哈希表的结合,由哈希表保证去重,有链表保证存取顺序
      • TreeSet : 有序(排序规则)
  • Map: HashMap/TreeMap…
    • HashMap : 无序
    • TreeMap : 有序
  • Collections : Collection 集合的工具类, 排序/逆序/洗牌…(都是静态方法)
  • Properties : 和 Map 集合用法相同,并具有自身特有的获取与设置成员的方法.通常用于IO操作,应用于配置文件的读写居多

01-Java中的集合相关推荐

  1. java去重复的集合_如何去除Java中List集合中的重复数据

    1.循环list中的所有元素然后删除重复 public class duplicatRemoval { public static List removeDuplicate(List list){ f ...

  2. Java中Set集合是如何实现添加元素保证不重复的?

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | 公众号「武培轩」 Java中Set集合是如何实 ...

  3. 万字长文深入理解java中的集合-附PDF下载

    文章目录 1. 前言 2. List 2.1 fail-safe fail-fast知多少 2.1.1 Fail-fast Iterator 2.1.2 Fail-fast 的原理 2.1.3 Fai ...

  4. (转)java中对集合对象list的几种循环访问总结

    Java集合的Stack.Queue.Map的遍历 在集合操作中,常常离不开对集合的遍历,对集合遍历一般来说一个foreach就搞定了,但是,对于Stack.Queue.Map类型的遍历,还是有一些讲 ...

  5. java中的集合框架_JAVA中的集合框架(上)List

    第一节 JAVA中的集合框架概述 集合的概念,现实生活中:很多事物凑在一起就是一个集合:数学中的集合:具有相同属性事物的总体:JAVA中的集合:是一种工具类,就像是容器,储存任意数量的具有共同属性的对 ...

  6. java中各种集合的用法和比较

    一,java中各种集合的关系图 Collection       接口的接口     对象的集合  ├ List           子接口         按进入先后有序保存   可重复  │├ L ...

  7. java中的集合_Java 集合介绍,常用集合类

    JAVA 集合 在处理数据的过程中经常会需要一个容器来存储某一类型的数据,Java 中的数组就是这样一种容器.但 Java 中的数组有其局限性,定义后的数组长度不可变,超出数组长度后就不能再存放数据了 ...

  8. java 中的集合_JAVA中的集合

    JAVA中集合,是java中的基础概念,今天接着跟讲课准备课件的机会,重新整理一下关于JAVA中的集合的概念. 集合的概念 java中的集合类是用来存放对象的 集合相当于一个容器,里面包容着一组对象- ...

  9. Java中List集合的三种遍历方式(全网最详)

    Map集合:链接: Map集合的五种遍历方式及Treemap方法 Set集合:链接: Java中遍历Set集合的三种方法 TreeSet集合:链接: Java深入了解TreeSet,和迭代器遍历方法 ...

  10. 10.JAVA中的集合(数据结构)

    Java中的集合 包含以下结构: 数组-线性表 链表 栈 队列 散列表 二叉树 映射关系(key-value) List集合  特点:[有序.重复] [线性表--数组] ArrayList 定义 线程 ...

最新文章

  1. 利用Use Case为系统行为建模(3)
  2. 支付宝,马云其人与我们的心态
  3. TCP服务器和客户端的链接例子(侧重点在注意关闭套接子,减少套接子的描述子)
  4. Python基础教程(八):日期和时间、文件I/O、异常处理
  5. EasyUI环境搭建与入门基础语法
  6. 初创公司 经营_LibreCorps指导人道主义初创公司如何运行开源方式
  7. php xingnengfenxi_php代码性能分析方法
  8. JavaScript之改变样式
  9. 塞尔达传说gba_1986版塞尔达 回顾34年经典系列历代作品 满分最多系列游戏
  10. python面向对象类的成员_Python面向对象中类的成员
  11. (一) 双目立体视觉介绍
  12. era5数据内容说明_接口测试:A04_HttpRunner通用_02_提取数据_01_extract关键字
  13. hadoop2.8配置_hadoop2.8安装教程
  14. Java视频教程免费分享
  15. 第十章--聚类分析 第5组 小组作业
  16. java 代码块 构造函数_Java学习笔记之------构造函数,静态关键字,静态代码块,构造代...
  17. 电脑怎么既录屏又录人脸?分享2个宝藏方法,轻松学会
  18. html如何控制图片自动放缩,如何用js控制图片放大缩小
  19. 什么是闭包,闭包是怎么产生的,闭包的应用在什么地方
  20. Vue实现底部导航栏切换页面及图片

热门文章

  1. 网络传输的两种方式——同步传输和异步传输的区别
  2. yilia 的html模板,Hexo搭建个人博客:yilia主题配置(七) - 自定义Subnav图标
  3. USYD悉尼大学DATA1002 详细作业解析Module3
  4. 【电力电子技术DC-DC】Boost升压式变换器Simulink仿真
  5. Win系统 - 你知道 insert 键的隐藏功能吗?
  6. web前端第一次作业
  7. java bigdecimal 取整数_java-检查BigDecimal是否为整数值
  8. Browserslist: caniuse-lite is outdated. Please run the following command: `npm update`
  9. 密码学_最近在论证一个问题,到底是先有鸡还是先有蛋
  10. Word文档快速调整表格列宽度