当前位置:   article > 正文

Java基础阶段0-常用数据结构_java数组结构

java数组结构
一,Java数组结构之数组
1.1数组的定义

        数组:具有相同数据类型元素组成的有限数据集合。除第一个元素外,每个元素都有唯一的前驱;除最后一个元素外,每个元素都有唯一的后继。

        数组的定义在计算机中的特性(Java语言):数组元素均存储在内存中是一段连续的空间,且每个元素都有自己的编号。注:Java中数组下标从0开始。

1.2数组的创建及初始化

        数组:用于批量处理数据。可分为静态数组和动态数组:a) 静态数组:是数组在声明的时候就已经定义了数组的元素(即数组元素的个数固定不变),分配的存储空间在栈上;b)动态数组: 定义数组时不先存入具体的元素值, 只确定数组存储的数据类型和数组的长度。

       a) 静态数组初始化结构:

                 1,完整格式: 数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, 元组3, 。。。}                                   eg: int[] ages = new int[]{12,24,36};

                 2,简洁格式: 数据类型[] 数组名 = {元素1, 元素2, 元素3, 。。。}

                                 eg: double names = {13.14, 520.99, 888.666}

        b) 数组的动态初始化格式: 数据类型[] 数组名 = new 数据类型[长度];

  1. //目标: 掌握静态数组的定义
  2. int[] ages = new int[]{12, 24, 36};
  3. double[] scores = new double[]{89.8, 59.4, 88.0};
  4. String[] names = {"rose", "anli", "jake"}; //简洁方式
  5. int ages2[] = new int[]{12, 34, 56}; //不报错,但是建议写在前面。别人一看就知道是数组
  6. //数据类型[] 数组名 = new 数据类型[长度];
  7. int[] ages = new int[3]; //其实是有初始化的 ages = [0,0,0]

        温馨提示:

        1,数据类型[] 数组名 ----也可以写成---> 数据类型 数组名[]; 但是不推荐

        2,什么类型的数组 就只能存储什么类型的数据;

        3,静态和动态的数组初始化写法是独立的,不可以混用:

                eg: int[] array = new int[5] {1,2,3,4,5};  //混用了,会报错!!!

        4,动态初始化数组时,其实是有默认值的(不要以为没有值只是创建了array.length大小是内存空间)。(代码如下)

  1. /*
  2. 动态初始化数组元素默认值规则:
  3. byte, short, int , char, long : 0
  4. 基本数据类型 float double : 0.0
  5. boolean : false
  6. 引用数据类型 类,接口,数组,String :null
  7. */
  8. char[] chars = new char[10];
  9. System.out.println(chars[0]); //运行结果: (ASCII码)为0的字符
  10. System.out.println((int) chars[1]); //运行结果: 0
  11. int[] num = new int[10];
  12. System.out.println(num[0]); //运行结果: 0
  13. System.out.println(num[9]); //运行结果: 0
  14. String[] names = new String[5];
  15. System.out.println(names[0]); //运行结果: null
  16. System.out.println(names[4]); //运行结果: null
  17. }
1.3数组的使用

        【引用该作者的优秀总结】:数组在内存中是一段连续的空间,空间的编号都是从0开始的,依次递增,该编号称为数组的下标,也可以说是数组的索引。数组可以通过下标访问其任意位置的元素。且数组支撑随机访问噢。

  1. //数组的访问,用下标访问, 数组下标从零开始哦。 数组的长度属性: array.length
  2. for (int i = 0; i < names.length; i++) {
  3. System.out.println(names[i]); //实现了数组的遍历
  4. }
  5. //修改数组中的数据
  6. ages2[0] = 1314;
  7. ages2[2] = 520;
  8. System.out.println(ages2[0]);
  9. System.out.println(ages2[1]);
  10. System.out.println(ages2[2]);

        数组遍历时,可以在数组中可以通过 数组对象 .length 来获取数组的长度 (But 数组对象不能为null)

  1. {
  2. //数组的遍历,案例分析
  3. //快捷键: 数组名.length.fori
  4. int[] nums = new int[] {12,2342,45,78};
  5. for (int i = 0; i < nums.length; i++) {
  6. System.out.println(nums[i]);
  7. }
  8. //案例:数组求和
  9. int sum = 0;
  10. for (int i = 0; i < nums.length; i++) {
  11. sum += nums[i];
  12. }
  13. System.out.println(sum);
  14. }
二,Java数组结构之链表
1链表的定义

        链表:就是链式的线性表(线性表的特性:除第一个元素外,每个元素都有唯一的前驱;除最后一个元素外,每个元素都有唯一的后继。So数组和链表的线性表的两种最基本的形式)。链表是由一个个独立的元素(称之为结点)线性连接起的, 因此链表是有一系列的结点组成的,在C++中通过指针ListNode *next进行连接, 在Java中通过引用ListNode next进行连接。(关于C++的指针与Java的引用:很重要的知识点!!!参看文章【C++指针 和 Java引用】)

        链表的类型:有单连表、双链表、循环链表、循环双链表、静态链表等等,本文最要讲单连表,其余类型根据其类型特性举一反三嘛。

  1. //Java 单连表的定于
  2. public class ListNode {
  3. // 结点的值
  4. int val;
  5. // 下一个结点
  6. ListNode next;
  7. // 节点的构造函数(无参)
  8. public ListNode() {
  9. }
  10. // 节点的构造函数(有一个参数)
  11. public ListNode(int val) {
  12. this.val = val;
  13. }
  14. // 节点的构造函数(有两个参数)
  15. public ListNode(int val, ListNode next) {
  16. this.val = val;
  17. this.next = next;
  18. }
  19. //三个构造函数: 又是函数重载的知识
  20. }
2,链表的创建及初始化

        链表创建语句格式: ListNode 链表名(或者结点名) =  new ListNode(),此时会调用默构造函数public ListNode(){ }。

  1. public class UseList {
  2. public static void main(String[] args) {
  3. //创建一个ListNode对象, 使用三种不同构造函数
  4. ListNode listNode1 = new ListNode();
  5. ListNode listNode2 = new ListNode(10);
  6. ListNode listNode3 = new ListNode(20,listNode2); //listnode3的next指向listnode2
  7. //调用ListNode对像
  8. listNode1.val = 0;
  9. System.out.println(listNode1.val);
  10. listNode2.next = listNode1; //此时有listnode3 -> listnode2 -> listnode1
  11. System.out.println(listNode3.next.next.val); //listnode1.val
  12. System.out.println(listNode3.next.val); //listnode2.val
  13. System.out.println(listNode3.next); //在打印 listnoded2
  14. //class 起到了封装作用,当成员变量(val, next等定义为private时)不允许直接使用ListNode对象的变量val,next
  15. //但是我们可以在class类中定义函数,在函数里面可以调用它啊。从而起到了封装保护的作用
  16. }
  17. }

运行结果:

0
0
10
com.tsm.list.ListNode@3b07d329        //说明 Java定义next的时候用ListNode next; 没有C++中的‘*’, 因为Java中是引用!!!。 很明显直接打印listnode2,结果为一个地址。(写错了请大佬指正!!!我没求证得了)

3,链表的使用

        为了使得对链表的使用更加方便,我们可以去丰富自己所定义的ListNode类:创建一些有用的方法(函数)供ListNode对象进行调用,以达到方便、高效、健壮的目的。

         再次封装List Node类,以实现将val和next当作一个结点来看待(疑问:不进行封装行不行?)。定义ListNode class:  这里private int val: 之后不可以直接对ListNode对象.val进行操作。但是可以通过ListNode对象.getval() ListNode对象.setval()进行赋值与取值。

  1. package com.tsm.list;
  2. public class ListNode {
  3. //int val; //结点的值
  4. private int val; //定义为私有变量,不允许直接访问
  5. ListNode next; //下一个结点
  6. //函数的构造函数
  7. public ListNode(){
  8. }
  9. public ListNode(int val){
  10. this.val = val;
  11. this.next = null;
  12. }
  13. public ListNode(int val, ListNode node){
  14. this.val = val;
  15. this.next = node;
  16. }
  17. //private 的变量val,可以通过getval, setval函数来进行复制与使用
  18. public int getVal() {
  19. return val;
  20. }
  21. public void setVal(int val) {
  22. this.val = val;
  23. }
  24. }
  1. package com.tsm.list;
  2. public class LinkedList {
  3. //实现对ListNode类的封装, 将ListNode对象的val, next当作一个整体来看待
  4. ListNode head;
  5. public LinkedList(){
  6. this.head = null;
  7. }
  8. /*public ListNode getHead() {
  9. return head;
  10. }
  11. public void setHead(ListNode head) {
  12. this.head = head;
  13. }*/
  14. //一下函数均想采用带虚拟头结点的单连表,来做
  15. //遍历单连表,打印所有值。
  16. public void printAll(){ //是在写成员函数,不是写一般的函数,不需要传入LinkedList head
  17. ListNode realHead = new ListNode(0, head);
  18. ListNode current = realHead;
  19. while (current.next != null){
  20. System.out.println(current.next.getVal() );
  21. current = current.next;
  22. }
  23. }
  24. //获取链表中第 index 个节点的值。如果索引无效,则返回-1。
  25. public int getIndex(int index){
  26. if (index <= 0){
  27. return -1; //index是位序从1开始,123456789...
  28. }
  29. ListNode realHead = new ListNode(0, head);
  30. ListNode current = realHead;
  31. while(current.next != null && index >= 1){
  32. current = current.next;
  33. index--;
  34. }
  35. return index != 0 ? -1 : current.getVal();
  36. }
  37. //在链表最前面插入一个节点,等价于在第1个元素前添加
  38. public void addAtHead(int data){
  39. //等于addIndex(1, data);
  40. ListNode newNode = new ListNode(data, null);
  41. if (head == null){
  42. head = newNode;
  43. }else {
  44. newNode.next = head;
  45. head = newNode;
  46. }
  47. }
  48. // 在链表尾部插入节点
  49. public void addAtTail(int data) {
  50. ListNode newNode = new ListNode(data,null);
  51. ListNode realHead = new ListNode(0, head);
  52. ListNode current = realHead;
  53. while (current.next != null){
  54. current = current.next; //遍历至最后一个结点
  55. }
  56. current.next = newNode;
  57. //不用返回,因为对象,数组是引用数据类型。 newNode是一个对象!
  58. }
  59. //删除第index个节点, index:1,2,3,4,5,6,7,8,9,...
  60. public void deleteIndex(int index){
  61. if (index <= 0){
  62. return; //index是位序从1开始,123456789...
  63. }
  64. ListNode realHead = new ListNode(0, head);
  65. ListNode current = realHead;
  66. //遍历找到第index - 1个结点
  67. while( current.next != null && index > 1){
  68. //current 前进index-1步,指向第index-1个结点
  69. current = current.next;
  70. index--;
  71. }
  72. if (current == null || current.next == null){
  73. return; //index过大了,超过链表长度
  74. } else{
  75. current.next = current.next.next;;
  76. }
  77. }
  78. //插入第index个结点
  79. public void addIndex(int index, int data){
  80. if (index <= 0){
  81. return;
  82. }
  83. ListNode realHead = new ListNode(0, head);
  84. ListNode current = realHead;
  85. while (current != null && index > 1){
  86. current= current.next; //current指向第index-1个结点
  87. index--;
  88. }
  89. if (current == null){
  90. return; //index过大
  91. }if (current.next == null){
  92. ListNode newNode = new ListNode(data, null);
  93. current.next = newNode;
  94. }else {
  95. ListNode newNode = new ListNode(data, current.next);
  96. current.next = newNode;
  97. }
  98. }
  99. }
  1. package com.tsm.list;
  2. public class UseList {
  3. public static void main(String[] args) {
  4. {
  5. //链表的创建、初始化和使用
  6. //创建一个ListNode对象, 使用三种不同构造函数
  7. ListNode listNode1 = new ListNode();
  8. ListNode listNode2 = new ListNode(10);
  9. ListNode listNode3 = new ListNode(20, listNode2); //listnode3的next指向listnode2
  10. //调用ListNode对象
  11. listNode1.setVal(0);
  12. System.out.println(listNode1.getVal());
  13. listNode2.next = listNode1; //此时有listnode3 -> listnode2 -> listnode1
  14. System.out.println(listNode3.next.next.getVal()); //listnode1.val
  15. System.out.println(listNode3.next.getVal()); //listnode2.val
  16. System.out.println(listNode1);
  17. System.out.println(listNode3.next); //在打印 listnoded2
  18. System.out.println(listNode3);
  19. //class 起到了封装作用,当成员变量(val, next等定义为private时)不允许直接使用ListNode对象的变量val,next
  20. //但是我们可以在class类中定义函数,在函数里面可以调用它啊。从而起到了封装保护的作用
  21. }
  22. {
  23. //使用链表, 调用成员函数
  24. LinkedList head = new LinkedList(); //head为首元结点
  25. //在头部插入结点
  26. head.addAtHead(20);
  27. head.addAtHead(10);
  28. head.printAll(); //此时链表为10 -> 20 -> null
  29. //在尾部插入结点
  30. head.addAtTail(30);
  31. head.addAtTail(40);
  32. head.printAll(); //此时链表为10 -> 20 -> 30 -> 40 -> null
  33. //获取第3个结点的值
  34. int num3 = head.getIndex(3);
  35. System.out.println(num3); //结果为:30
  36. int num10 = head.getIndex(10);
  37. int num = head.getIndex(-2);
  38. System.out.println(num); //index < 1,结果返回-1
  39. System.out.println(num10); //index过大,结果返回-1
  40. //插入第三个结点,值为25
  41. head.addIndex(3, 25);
  42. head.printAll(); //此时链表为10 -> 20 -> 25 -> 30 -> 40 -> null
  43. //删除第5个结点
  44. head.deleteIndex(5);
  45. head.printAll(); //此时链表为10 -> 20 -> 25 -> 30 -> null
  46. //无效index
  47. head.deleteIndex(10);
  48. head.deleteIndex(-1);
  49. head.printAll(); //此时链表为10 -> 20 -> 25 -> 30 -> null
  50. }
  51. }
  52. }

三,Java数据结构之栈
1,Java中的栈        

        Java中了关于栈的定义类:public class Stack<E> extends Vector<E>

        API文档介绍如下: The Stack class represents a last-in-first-out (LIFO) stack of objects. It extends class Vector with five operations that allow a vector to be treated as a stack. The usual push and pop operations are provided, as well as a method to peek at the top item on the stack, a method to test for whether the stack is empty, and a method to search the stack for an item and discover how far it is from the top.

         When a stack is first created, it contains no items.

         A more complete and consistent set of LIFO stack operations is provided by the Deque interface and its implementations, which should be used in preference to this class. Deque<Integer> stack = new ArrayDeque<Integer>();

         文中意思: Stack类表示对象的后进先出(LIFO)堆栈。它用五个操作扩展了类Vector,这些操作允许将向量视为堆栈。 提供了常见的推送和弹出操作,以及一种查看堆栈上顶部项目的方法,一种测试堆栈是否为空的方法,以及一个在堆栈中搜索项目并发现它离顶部有多远的方法。          第一次创建堆栈时,它不包含任何项。

         Deque接口及其实现提供了一组更完整、更一致的LIFO堆栈操作,应该优先使用此类:Deque<Integer> stack = new ArrayDeque<Integer>();

2,栈的创建和初始化

        Stcak的一个类:属于Module:java.base; 属于包:java.util。Stack类的创建时只有一个构造器函数:Stack():Creates an empty Stack.也符号API文档介绍那样第一次创建栈时,它不包含任何项。

  1. //对Stack类的练习
  2. //1, 创建一个Stcak对象
  3. java.util.Stack<Integer> stack = new java.util.Stack<>();
3,栈的使用
常用方法:
    1,构造器:Stack() Creates an empty Stack.   介绍里也说了第一次创建堆栈时,它不包含任何项。

    2,5个扩展操作:
        boolean     empty()     Tests if this stack is empty.
        E           peek()      Looks at the object at the top of this stack without removing it from the stack.
        E           pop()       Removes the object at the top of this stack and returns that object as the value of this function.
        E           push(E item)        Pushes an item onto the top of this stack.

        int         search(Object o)    Returns the 1-based position where an object is on this stack.
        int search(Object o) :Returns the 1-based position where an object is on this stack. If the object o occurs as an item in this stack,this method returns the distance from the top of the stack of the occurrence nearest the top of the stack;the topmost item on the stack is considered to be at distance 1. The equals method is used to compare o to the items in this stack.
  1. public static void main(String[] args) {
  2. //对Stack类的练习
  3. //1, 创建一个Stcak对象
  4. java.util.Stack<Integer> stack = new java.util.Stack<>();
  5. //实现push(1) push(2) pop() peek() push(3) push(4) pop() push(5) pop() peek() pop() pop()
  6. // 2 1 4 5 3 3 1
  7. //2,调用函数
  8. stack.push(1);
  9. stack.push(2);
  10. System.out.println(stack.pop());
  11. System.out.println(stack.peek());
  12. stack.push(3);
  13. stack.push(4);
  14. System.out.println(stack.pop());
  15. stack.push(5);
  16. System.out.println(stack.pop());
  17. System.out.println(stack.peek());
  18. System.out.println(stack.pop());
  19. System.out.println(stack.pop());
  20. // 3,测试 empty() search()
  21. if (stack.empty()){
  22. System.out.println("栈为空");
  23. }else {
  24. System.out.println("栈非空");
  25. }
  26. stack.push(1);
  27. stack.push(2);
  28. stack.push(3);
  29. stack.push(4);
  30. stack.push(5);
  31. System.out.println("元素1在栈中的位置为: " + stack.search(1)); //离栈顶出现的第一个元素为1的距离
  32. System.out.println("元素4在栈中的位置为: " + stack.search(4)); //栈顶元素的距离视为 1
  33. }

运行结果:

2
1
4
5
3
3
1
栈为空
元素1在栈中的位置为: 5
元素4在栈中的位置为: 2

Process finished with exit code 0

四,Java数据结构之队列

        参考文章:https://blog.csdn.net/swadian2008/article/details/126783574

 1.1在Java中有哪些常见的队列?
      在Java中,有一些常见的队列实现。下面是其中一些的列举://队列也是一种线性的数据结构
      1,ArrayList:ArrayList可以被用作队列,通过在列表末尾添加元素,并使用remove(0)方法从列表的开头删除元素。
            但是,由于在列表的开头删除元素会导致后续元素的移动,因此对于大量的插入和删除操作来说,ArrayList的性能可能不是最佳选择。

      2,LinkedList:LinkedList也可以用作队列。LinkedList实现了Queue接口,可以使用offer()方法在队列的末尾添加元素,使用poll()方法从队列的开头删除并返回元素。
            LinkedList对于插入和删除操作具有较好的性能,因为它使用了指针来链接元素,而不需要移动其他元素。

      3,ArrayBlockingQueue:ArrayBlockingQueue是一个有界阻塞队列,底层使用数组实现。它有一个固定的容量,并且在插入或删除元素时可能会阻塞线程,直到满足特定的条件。
      4,LinkedBlockingQueue:LinkedBlockingQueue是一个可选有界或无界的阻塞队列,底层使用链表实现。它具有类似于ArrayBlockingQueue的功能,但在内部实现上略有不同。
      5,PriorityBlockingQueue:PriorityBlockingQueue是一个支持优先级的无界阻塞队列。元素按照它们的优先级顺序被插入和删除。
      6,ConcurrentLinkedQueue:ConcurrentLinkedQueue是一个非阻塞无界队列,它适用于多线程环境。它使用链表实现,并且提供了高效的并发操作。

       以上是Java中的一些常见队列实现。具体选择哪种队列取决于你的需求和使用场景。
  1.2Queue接口分析
        Java中了关于队列的定义接口: public interface Queue<E> extends Collection<E>

        API文档介绍如下:
        A collection designed for holding elements prior to processing. Besides basic Collection operations,
queues provide additional insertion, extraction, and inspection operations. Each of these methods exists in two forms:
one throws an exception if the operation fails, the other returns a special value (either null or false,
depending on the operation). The latter form of the insert operation is designed specifically for use with
capacity-restricted Queue implementations; in most implementations, insert operations cannot fail.

        中文翻译:
        一种设计用于在加工前固定元件的集合。除了基本的集合操作外,队列还提供额外的插入、提取和检查操作。
        这些方法中的每一种都有两种形式:一种是在操作失败时抛出异常,另一种是返回特殊值(null或false,具体取决于操作)。
        后一种形式的插入操作是专门为与容量受限的队列实现一起使用而设计的;在大多数实现中,插入操作不会失败。
2,队列的创建和初始化

        创建一个Queue对象: 不能直接Queue<E> queue = new Queue<>();

        原因:Java中的Queue是一个接口,而接口是不能创建对象的。因此我们需要选择一个具体的实现类,来创建一个队列对象。

        eg:LinkedList类:它实现了Queue接口。因此可用LinkedList类创建Queue对象:

  1. //1, 创建一个Queue对象
  2. java.util.Queue<String> queue = new LinkedList<>();
  3. //知道这里为什么只能写成java.util.Queue吗,因为有两个都叫Queue(自己已经定义了一个了,而且先用), 所有后用者得全称

        

Tips:关于一些接口的知识点:参看文章:https://blog.51cto.com/u_13539/6762135  

        1、接口中一般定义常量和抽象方法,而且常量和方法一般有默认修饰符:

                常量:public static final                方法:public abstract

        2、接口不能创建对象,接口的子类必须重写接口所有的方法后才能够创建对象。

        3、java不支持多继承,因为如果多继承,当子类引用调用某函数而该函数又在多个父类中出现时,java虚拟机将不知道到底该调用哪个父类中的该函数。而多实现,子类引用调用多个父接口都有的函数时,因为父接口的该函数都是虚拟的没有函数体,在子类中肯定会有对该父接口虚拟函数的重写,子类就会调用子类中的该函数,不存在java虚拟机疑惑的问题。

        4、类与类的关系是继承(当然也有其他关系),类与接口的关系是实现,接口与接口之间的关系也是继承。

3,队列的使用
常用方法:
1,Collection接口的方法:Methods declared in interface java.util.Collection
    addAll, clear, contains, containsAll, equals, hashCode, isEmpty, iterator, parallelStream,    remove, removeAll, removeIf, retainAll, size, spliterator, stream, toArray, toArray, toArray

2,Queue接口定义的方法:
                             Summary of Queue methods
                  Throws exception     Returns special value
       Insert           add(e)              offer(e)
       Remove          remove()             poll()
       Examine         element()            peek()
  1. Modifier and Type Method Description
  2. boolean add(E e) Inserts the specified element into this queue if it is possible to do so immediately without violating capacity restrictions,
  3. returning true upon success and throwing an IllegalStateException if no space is currently available.
  4. boolean offer(E e) Inserts the specified element into this queue if it is possible to do so immediately without violating capacity restrictions.
  5. E element() Retrieves, but does not remove, the head of this queue.
  6. E peek() Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty.
  7. E poll() Retrieves and removes the head of this queue, or returns null if this queue is empty.
  8. E remove() Retrieves and removes the head of this queue.
  1. public static void main(String[] args) {
  2. //练习方法:
  3. //怎么办:Queue是一个接口,不像Stack是一个类 :Queue queue = new Queue();这个代码是不行的
  4. //当使用Java中的Queue接口时,我们需要选择具体的实现类来创建一个队列对象。下面是一个使用Queue接口的示例,以LinkedList实现类为例:
  5. //1, 创建一个Queue对象
  6. java.util.Queue<String> queue = new LinkedList<>();
  7. //知道这里为什么只能写成java.util.Queue吗,因为有两个都叫Queue(自己已经定义了一个了,而且先用), 所有后用者得全称
  8. // 2,添加元素到队尾 返回值:boolean
  9. queue.add("blue"); //继承的Collection方法
  10. queue.offer("red"); //Queue接口定义的方法,且不会抛出异常
  11. queue.add("white");
  12. queue.offer("block");
  13. //获取队列头部元素 返回值:E
  14. String res1 = queue.peek(); //不会抛出异常
  15. String res2 = queue.element(); //可能抛出异常
  16. System.out.println("res1 = " + res1);
  17. System.out.println("res2 = " + res2);
  18. System.out.println("遍历队列Queue:");
  19. for (String res : queue){
  20. System.out.println(" " + res);
  21. }
  22. //移除队列头部元素 返回值:E
  23. String ele1 = queue.poll(); //不会抛出异常
  24. String ele2 = queue.remove(); //可能抛出异常
  25. System.out.println("ele1 = " + ele1);
  26. System.out.println("ele2 = " + ele2);
  27. //判断队列是否为空
  28. boolean isEmpty = queue.isEmpty();
  29. System.out.println("队列是否为空:" + isEmpty);
  30. System.out.println("队列长度为: " + queue.size()); //size()是Collection接口定义的方法
  31. }

运行结果:

    res1 = blue
    res2 = blue
    遍历队列Queue:
        blue
        red
        white
        block
    ele1 = blue
    ele2 = red
    队列是否为空:false
    队列长度为: 2

Process finished with exit code 0

五,Java数据结构之双端队列

                                                栈与队列的尽头是双端队列。

1,Deque接口
        Java中了关于Deque的定义接口 :public interface Deque<E> extends Queue<E>
        All Superinterfaces:    Collection<E>, Iterable<E>, Queue<E>

        API文档介绍如下:
        A linear collection that supports element insertion and removal at both ends.
The name deque is short for "double ended queue" and is usually pronounced "deck".
Most Deque implementations place no fixed limits on the number of elements they may contain,but this interface supports capacity-restricted deques as well as those with no fixed size limit.

        This interface defines methods to access the elements at both ends of the deque.Methods are provided to insert, remove, and examine the element. Each of these methods exists in two forms:one throws an exception if the operation fails, the other returns a special value (either null or false, depending on the operation).The latter form of the insert operation is designed specifically for use with capacity-restricted Deque implementations;in most implementations, insert operations cannot fail.

        中文翻译:
        支持在两端插入和删除元素的线性集合。deque是“双端队列”的缩写,通常发音为“deck”。大多数Deque实现对其可能包含的元素数量没有固定的限制,但此接口支持容量受限的Deque以及没有固定大小限制的Deque。

        这个接口定义了访问deque两端元素的方法。提供了插入、移除和检查元素的方法。这些方法中的每一种都有两种形式:一种是在操作失败时抛出异常,另一种是返回特殊值(null或false,具体取决于操作)。插入操作的后一种形式是专门为与容量受限的Deque实现一起使用而设计的;在大多数实现中,插入操作不会失败。
 2,Deque对象的创建
        Deque接口的常见实现类包括ArrayDeque和LinkedList。ArrayDeque是一个基于数组实现的双端队列,支持高效的随机访问和动态扩展。LinkedList是一个基于链表实现的双端队列,支持高效的插入和删除操作。
        通过使用Deque接口,我们可以方便地进行双端队列操作,如在队列的头部和尾部插入和删除元素,获取头部和尾部元素,以及判断队列是否为空。Deque在许多场景下都很有用,比如实现LRU缓存、实现任务调度等。
  1. java.util.Deque<Integer> deque = new ArrayDeque<>(); //采用数组版:尽量不要在头部做插入删除操作
  2. java.util.Deque<Integer> deque1 = new LinkedList<>(); //采用链表版:支持高效的插入和删除操作

Deque的使用!!!

        说了栈与队列的尽头是双端队列,是因为双端队列能实现栈和队列的功能。因为Deque的方法使用分三部分:分别将Deque对象当作双端队列、栈和队列来使用。

3.1Deque之双端队列的使用
  1. 常用方法:
  2. 1,作为双端队列:The twelve methods described above are summarized in the following table:
  3. Summary of Deque methods
  4. First Element (Head) Last Element (Tail)
  5. Throws exception Special value Throws exception Special value
  6. Insert addFirst(e) offerFirst(e) addLast(e) offerLast(e)
  7. Remove removeFirst() pollFirst() removeLast() pollLast()
  8. Examine getFirst() peekFirst() getLast() peekLast()
  9. 方法总结Method Summary:
  10. 1)添加元素:
  11. void addFirst(E element): 将指定元素添加到双端队列的头部。
  12. void addLast(E element): 将指定元素添加到双端队列的尾部。
  13. boolean offerFirst(E element): 将指定元素添加到双端队列的头部,如果成功则返回true,如果队列已满则返回false
  14. boolean offerLast(E element): 将指定元素添加到双端队列的尾部,如果成功则返回true,如果队列已满则返回false
  15. 2)移除元素:
  16. E removeFirst(): 移除并返回双端队列的头部元素,如果队列为空则抛出异常。
  17. E removeLast(): 移除并返回双端队列的尾部元素,如果队列为空则抛出异常。
  18. E pollFirst(): 移除并返回双端队列的头部元素,如果队列为空则返回null
  19. E pollLast(): 移除并返回双端队列的尾部元素,如果队列为空则返回null
  20. 3)获取头部和尾部元素:
  21. E getFirst(): 获取双端队列的头部元素,但不移除它,如果队列为空则抛出异常。
  22. E getLast(): 获取双端队列的尾部元素,但不移除它,如果队列为空则抛出异常。
  23. E peekFirst(): 获取双端队列的头部元素,但不移除它,如果队列为空则返回null
  24. E peekLast(): 获取双端队列的尾部元素,但不移除它,如果队列为空则返回null
  25. Deque接口还提供了一些其他方法,如size
  1. public static void show1(java.util.Deque<Integer> deque){
  2. System.out.println("遍历双端队列Deque(从头到脚) :");
  3. for (Object ele : deque){
  4. System.out.print(ele + " ");
  5. }
  6. System.out.println();
  7. }
  8. public static void main(String[] args) {
  9. //练习:
  10. {
  11. //练习双端队列
  12. java.util.Deque<Integer> deque = new ArrayDeque<>(); //采用数组版:尽量不要在头部做插入删除操作
  13. //java.util.Deque<Integer> deque1 = new LinkedList<>(); //采用链表版:支持高效的插入和删除操作
  14. //插入元素:左右开弓
  15. deque.add(0);
  16. deque.addFirst(-1);
  17. deque.addLast(1);
  18. deque.offerFirst(-2);
  19. deque.offerLast(2);
  20. show1(deque);
  21. //获取双端队列头部和尾部元素
  22. int front = deque.getFirst();
  23. int nail = deque.peekLast();
  24. System.out.println("头部元素" + front);
  25. System.out.println("尾部元素" + nail);
  26. //移除双端队列头部和尾部元素
  27. int removedFirst = deque.removeFirst();
  28. int removedLast = deque.removeLast();
  29. System.out.println("移除第一个的头部元素:" + removedFirst);
  30. System.out.println("移除第一个的尾部元素:" + removedLast);
  31. int removedFirst2 = deque.pollFirst();
  32. int removedLast2 = deque.pollLast();
  33. System.out.println("移除第二个的头部元素:" + removedFirst2);
  34. System.out.println("移除第二个的尾部元素:" + removedLast2);
  35. // 双端队列大小
  36. int size = deque.size();
  37. System.out.println("双端队列大小:" + size);
  38. // 判断双端队列是否为空
  39. boolean isEmpty = deque.isEmpty();
  40. System.out.println("双端队列是否为空: " + isEmpty);
  41. //清空队列:Collection接口中的方法
  42. deque.clear();
  43. }
  44. }
3.2Deque之队列的使用
  1. 2,作为队列:This interface extends the Queue interface. When a deque is used as a queue, FIFO (First-In-First-Out) behavior results.
  2. Elements are added at the end of the deque and removed from the beginning. The methods inherited from the Queue interface are precisely
  3. equivalent to Deque methods as indicated in the following table:
  4. Comparison of Queue and Deque methods
  5. Queue Method Equivalent Deque Method
  6. add(e) addLast(e)
  7. offer(e) offerLast(e)
  8. remove() removeFirst()
  9. poll() pollFirst()
  10. element() getFirst()
  11. peek() peekFirst()

        虽然定义的是Deque对象,但是除了addFirst(), offerFirst(), addLast(), offerLast()等等之外,Deque对象也有add(e), offer(e), peer(), element(), remove(), poll()等方法可用使用。因为Deque接口继承于Queue接口。 所有Deque接口的实现类必须实现接口Deque中定义的方法以及接口Queue 中定义的方法 。

Tips:interface A extends interface B        

        接口A继承接口B作用: 1.接口A中不用重写接口B中方法

        2.接口A的实现类必须实现接口A中定义的方法以及接口B中定义的方法。在实例化此实现类过程中恰恰体现了多态的特性,实例化对象可调用接口A、B中所有方法。

  1. public static void show2(java.util.Deque<String> deque){
  2. System.out.println("遍历双端队列Deque(从头到脚) :");
  3. for (Object ele : deque){
  4. System.out.print(ele + " ");
  5. }
  6. System.out.println();
  7. }
  8. public static void main(String[] args) {
  9. {
  10. //Deque当作队列使用:
  11. java.util.Deque<String> deque = new LinkedList<>(); //LinkedList类继承与Deque接口,继承与Queue接口
  12. deque.add("Apple"); //等价于Deque双端队列的 addLast(E e)
  13. deque.add("Banana");
  14. deque.offer("Orange"); //等价于Deque双端队列的 offerLast(E e)
  15. deque.offer("Pear");
  16. show2(deque);
  17. String str1 = deque.peek(); //等价于Deque双端队列的 peekFirst(E e)
  18. String str2 = deque.element(); //等价于Deque双端队列的 getFirst(E e)
  19. System.out.println("队列头部元素:" + str1);
  20. System.out.println("队列头部元素:" + str2);
  21. String str3 = deque.remove(); //等价于Deque双端队列的 removeFirst(E e)
  22. String str4 = deque.poll(); //等价于Deque双端队列的 pollFirst(E e)
  23. System.out.println("移除队列头部元素:" + str3);
  24. System.out.println("移除队列头部元素:" + str4);
  25. System.out.println("队列此时的长度为 " + deque.size());
  26. }
  27. }
3.3Deque之栈的使用
  1. 3,作为栈:Deques can also be used as LIFO (Last-In-First-Out) stacks.
  2. This interface should be used in preference to the legacy Stack class. When a deque is used as a stack,
  3. elements are pushed and popped from the beginning of the deque. Stack methods are equivalent to Deque methods as indicated in the table below:
  4. Comparison of Stack and Deque methods
  5. Stack Method Equivalent Deque Method
  6. push(e) addFirst(e)
  7. pop() removeFirst()
  8. peek() getFirst()
  1. public static void show1(java.util.Deque<Integer> deque){
  2. System.out.println("遍历双端队列Deque(从头到脚) :");
  3. for (Object ele : deque){
  4. System.out.print(ele + " ");
  5. }
  6. System.out.println();
  7. }
  8. public static void main(String[] args) {
  9. {
  10. //使用Deque模拟栈的使用
  11. java.util.Deque<Integer> stack = new LinkedList<>();
  12. // push(e) addFirst(e)
  13. // pop() removeFirst()
  14. // peek() getFirst()
  15. stack.push(520); //等价于Deque双端队列的 addFirst(e)
  16. stack.push(1314); //等价于Deque双端队列的 addFirst(e)
  17. stack.push(9999); //等价于Deque双端队列的 addFirst(e)
  18. show1(stack);
  19. int ele = stack.peek(); //等价于Deque双端队列的 getFirst()
  20. System.out.println(ele);
  21. int num1 = stack.pop(); //等价于Deque双端队列的 removeFirst()
  22. int num2 = stack.pop(); //等价于Deque双端队列的 removeFirst()
  23. int num3 = stack.pop(); //等价于Deque双端队列的 removeFirst()
  24. System.out.println("移除第一个栈顶元素: " + num1 );
  25. System.out.println("移除第二个栈顶元素: " + num2 );
  26. System.out.println("移除第三个栈顶元素: " + num3 );
  27. System.out.println(stack.isEmpty() ? "栈为空" : "栈不为空");
  28. }
  29. }

Tips:bianchengxiaozhishi

  1. /*
  2. 关于 整块代码前进后退一个tab键
  3. 首先选中该段代码,
  4. 按 Tab 增加一个tab键的空格
  5. 按 Shift + Tab 删除一个tab键的空格
  6. 关于 Java 的main方法中无法调用自身所在类的其他方法的两种解决办法
  7. ①创建一个Demo1的实例,然后通过该实例调用方法test
  8. public class Demo1{
  9. public static void main(String[] args){
  10. Demo1 d1 = new Demo1();
  11. d1.test();
  12. }
  13. public void test(){
  14. //代码
  15. }
  16. }
  17. ②将test方法声明为静态,就是在void前面添加static。
  18. 原因是main方法已经声明为静态,静态方法只能调用静态方法,而静态的方法无法调用非静态方法,而非静态方法可以调用静态方法。
  19. public class Demo1{
  20. public static void main(String[] args){
  21. test();
  22. }
  23. public static void test(){
  24. }
  25. }
  26. */

六,Java数据结构之集合

 本节知识点参考文章:     Java语言程序设计— Java中集合类的使用—集合概述、Collection接口、List接口、Set、Queue接口、Map接口icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/573484580
Java语言程序设计— Java中集合类的使用icon-default.png?t=N7T8https://blog.51cto.com/u_13633/6732721Iterable(迭代器)的用法icon-default.png?t=N7T8https://www.cnblogs.com/aaaazzzz/p/13757645.html

1.1 集合的定义

        Java是面向对象的语言,为了方便存储和操作对象,Java建立了集合框架体系。集合是指具有某种特定性质的具体的或抽象的对象汇总而成的集体,有时集合也称之为容器,

        需要注意,在Java中不仅仅集合可以用来存储对象,数组也可以,但是数组长度固定,集合的长度是可变的Java集合只能存储引用类型的数据,不可以存储基本数据类型的数据,当我们向集合中存储基本数据类型数据时,系统会自动进行装箱操作将基本类型转换成对应的包装类型数据。

1.2 Collection接口和Iterable接口

        Collection接口:

        Collction 接口是 List、Set和Queue等接口的父接口,该接口里定义的方法既可用于操作List集合,也可用于操作Set和Queue集合。Collection接口里定义了一系列操作集合元素的方法。常用方法有: 

  1. public class colletcion {
  2. public static void main(String[] args) {
  3. Collection collection = new ArrayList(); //创建集合
  4. collection.add(1000); //添加元素
  5. collection.add("我爱中国"); //添加元素
  6. //打印集合
  7. System.out.println(collection);
  8. System.out.println(collection.size()); //集合长度
  9. //contians(X): 判断X是否在集合中
  10. if (collection.contains(1001)){
  11. System.out.println(1001 + "在集合collection中");
  12. }else {
  13. System.out.println(1001 + "不在集合collection中");
  14. }
  15. Collection collection1 = new HashSet();
  16. collection1.add(2000);
  17. collection1.add("I love you");
  18. collection1.addAll(collection);
  19. System.out.println(collection1);
  20. collection1.removeAll(collection);
  21. System.out.println(collection1);
  22. collection.clear();
  23. if (collection.isEmpty()){
  24. System.out.println("我空啦");
  25. }
  26. }
  27. }

运行结果:

        [1000, 我爱中国]
        2
        1001不在集合collection中
        [2000, I love you, 1000, 我爱中国]
        [2000, I love you]
        我空啦

Process finished with exit code 0

        

        上面例子中创建了两个Collection对象,一个是collection,一个是collection1,其中collection是实现类ArrayList的实例,而collection1是实现类HashSet的实例,虽然它们实现类不同,但都可以把它们当成Collection来使用,都可以使用add方法给它们添加元素,这里使用了Java的多态性。        

        Lterable接口:

        在开发过程中,经常需要遍历集合中的所有元素,针对这种需求,Java提供了一个专门用于遍历集合的接口——Iterator。Iterator,它是用来迭代访问Collection中元素的,因此也称为迭代器。可以通过Collection接口中的iterator()方法得到该集合的迭代器对象,只要拿到这个对象,使用迭代器就可以遍历这个集合。

 Java中的Iterator功能比较简单,并且只能单向移动:

  (1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。

  (2) 使用next()获得序列中的下一个元素。

  (3) 使用hasNext()检查序列中是否还有元素。

  (4) 使用remove()将迭代器新返回的元素删除。

  Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

  1. package com.tsm.collection.collection;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.Iterator;
  5. public class Iteration {
  6. public static void main(String[] args) {
  7. Collection collection = new ArrayList();
  8. collection.add(123);
  9. collection.add(186);
  10. collection.add(876);
  11. collection.add(547);
  12. collection.add(244);
  13. Iterator iteration = collection.iterator();
  14. while (iteration.hasNext()){
  15. System.out.println(iteration.next());
  16. }
  17. //for each方法
  18. for(Object objects : collection){
  19. System.out.println(objects);
  20. }
  21. }
  22. }
1.3 集合的分类

        Java中的集合类主要分为Set,List和Map三种体系:Set代表的是无序的,不能重复的集合;List代表的有序,可以重复的集合;Map代表的具有映射关系的集合

集合类只要由两个接口类派生而来,Collection和Map,Collection类下面又Set,Queue,List三个接口,Map下面派生出了HashMap,Hashtable等类。

        (1)List的实现类主要有ArrayList,LinkedList,Vector;

         (2)Set的实现类主要有HashSet和TreeSet;

         (3)Map的实现类主要有HashMap和TreeMap,HashTable;

        (看那个体系结构图,慢慢看就懂啦)

2.1Set(集)

        Set集合中元素是不可重复的。Set接口也是继承自Collection接口,自己也没怎么扩充新的方法,就是Collection那一套(add(), contains(), remove(), size(),isEmpty(), clean() )。

        Set中元素有无序性的特点,这里要注意,无序性不等于随机性,无序性指的是元素在底层存储位置是无序的。Set接口的主要实现类是HashSet和TreeSet。其中HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此能高效地存取。TreeSet底层是用二叉树来实现存储元素的,它可以对集合中元素排序。

2.2HashSet集合

        HashSet类是Set接口的典型实现,使用Set集合时一般都使用这个实现类。HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能HashSet不能保证元素的排列顺序,且不是线程安全的。另外,集合中的元素可以为null

通过一个例子来演示HashSet集合的使用:

  1. package com.tsm.collection.set;
  2. import java.util.*;
  3. public class hashSet {
  4. public static void main(String[] args) {
  5. Set set = new HashSet(); //创建hashSet对象
  6. //使用的方法和Collection接口中定义的一样
  7. set.add(null); //hashSet对象可以存入null!
  8. set.add(new String("Iloveyou"));
  9. set.add("red");
  10. set.add("red");
  11. set.add("block");
  12. set.add("yellow");
  13. set.add("blue");
  14. for (Object object : set){
  15. System.out.println(object);
  16. }
  17. }
  18. }

运行结果:

        null
        red
        blue
        yellow
        block
        Iloveyou

Process finished with exit code 0

结果分析:例中存储元素时,是先存入的“yellow”,后存入的“blue”,而运行结果正好相反(是按照hash算法来存储元素的),证明了HashSet存储的无序性但是如果多次运行,可以看到结果仍然不变,说明无序性不等于随机性,另外,例中存储元素时,存入了两个“red”,而运行结果中只有一个“red”,说明HashSet元素的不可重复性。

2.3TreeSet集合

        TreeSet类是Set接口的另一个实现类,TreeSet集合和HashSet集合都可以保证容器内元素的唯一性(Set集合的特点:无重复元素),但它们底层实现方式不同,TreeSet底层是用自平衡的排序二叉树实现(红黑树),所以它既能保证元素唯一性,又可以对元素进行排序。

TreeSet还提供一些特有的方法,如表所示:

        后续补充这部分知识点,相对来说一般都用的HashSet集合,而TreeSet使用的很小。

3.1List(列表)

        List集合中元素是有序的且可重复的,相当于数学里面的数列,有序可重复。使用此接口能够精确地控制每个元素插入的位置,用户可以通过索引来访问集合中的指定元素,List集合还有一个特点就是元素的存入顺序与取出顺序相一致。

        List接口中大量地扩充了Collection接口,拥有了比Collection接口中更多的方法定义,其中有些方法还比较常用。如表所示。 表中列出了List接口的常用方法,所有的List实现类都可以通过调用这些方法对集合元素进行操作。可以看出主要实现了    用户可以通过索引来访问集合中的指定元素这一特性。

3.2ArrayList集合

        ArrayList 是List的主要实现类,它是一个数组队列,相当于动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List接口,提供了相关的添加、删除、修改、遍历等功能。

        ArrayList集合中大部分方法都是从父类Collection和List继承过来的,其中,add()方法和get()方法用于实现元素的存取,接下来通过一个案例来学习ArrayList集合如何存取元素。如例所示。

  1. package com.tsm.collection.list;
  2. import java.util.ArrayList;
  3. public class arrayList {
  4. public static void main(String[] args) {
  5. ArrayList list = new ArrayList();
  6. list.add(520);
  7. list.add("hello world");
  8. System.out.println(list.size()); //获取list集合长度, 调用了Collection集合方法
  9. System.out.println(list.get(1)); //获取index=1的元素内容,调用了List集合方法
  10. }
  11. }

注:这里的索引下标是从0开始,最大的索引是size-1,若取值超出索引范围,则会报Index OutOf Bounds Exception异常。

        ArrayList底层是用数组来保存元素,用自动扩容的机制实现动态增加容量,因为它底层是用数组实现,所以插入和删除操作效率不佳,不建议用ArrayList做大量增删操作,但由于它有索引,所以查询效率很高,适合做大量查询操作。对应的可以引出死对头LinkedList(类似于 数组与链表的相爱相杀)

3.3LinkedList集合

        ArrayList在处理增加和删除操作时效率较低,为了解决这一问题,可以使用List接口的LinkedList实现类。LinkedList底层的数据结构是基于双向循环链表的,且头节点中不存放数据。对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高。

LinkedList除了具备增删效率高的特点,还为元素的操作定义了一些特有的常用方法,如表所示。

        代码带补充!!!

4.1Map接口

        参考连接:(建议直接去阅读作者的文章,我只是想记录自己的学习)

【Java 基础篇】Java Map 详解icon-default.png?t=N7T8https://blog.csdn.net/qq_21484461/article/details/131384612

java基础——Mapicon-default.png?t=N7T8https://blog.csdn.net/Flipped7777/article/details/130323598JAVA里Map java里map数据格式icon-default.png?t=N7T8https://blog.51cto.com/u_16099237/6493641

        在Java的集合框架中,Map接口用于存储键值对,提供了一种基于键进行查找和操作的数据结构。Map接口是一个键值对的集合,它继承自Collection接口中的size()isEmpty()等方法,同时还提供了根据键查找值的方法,以及添加、删除和更新键值对的方法。

  1. package com.tsm.collection.map;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. public class map {
  5. public static void main(String[] args) {
  6. Map<String, Integer> map = new HashMap();
  7. //public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。
  8. map.put("来福", 18);
  9. map.put("阿黄", 20);
  10. map.put("旺财", 22);
  11. //判断元素是否在map里面,
  12. if (map.containsKey("二狗")){ //判断key
  13. System.out.println("有二狗");
  14. }else {
  15. System.out.println("无二狗");
  16. }
  17. if (map.containsValue(20)){
  18. System.out.println("有" + 20 + "岁的妙龄狗狗");
  19. }
  20. //public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
  21. map.remove("来福");
  22. System.out.println(map);
  23. //public V get(Object key) 根据指定的键,在Map集合中获取对应的值。
  24. int age = map.get("阿黄");
  25. System.out.println("阿黄" + age + "岁");
  26. /*
  27. tips:
  28. 使用put方法时,若指定的键(key)在集合中没有,则没有这个键对应的值,返回null,并把指定的键值添加到集合中;
  29. 若指定的键(key)在集合中存在,则返回值为集合中键对应的值(该值为替换前的值),并把指定键所对应的值,替换成指定的新值。
  30. */
  31. map.put("旺财", 23);
  32. System.out.println(map.get("旺财"));
  33. }
  34. }
4.2Map的遍历

        1,通过键找值:通过元素中的键,获取键所对应的值

                获取Map中所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键;

                遍历键的Set集合,得到每一个键;

                根据键,获取键所对应的值。方法提示:get(K key)

        2,通过键值对:通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值。

        Entry键值对对象:  Map中存放的是两种对象,一种称为key(键),一种称为value(值),它们在在Map中是一一对应关系,这一对对象又称做Map中的一个Entry(项)。Entry将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map集合时,就可以从每一个键值对(Entry)对象中获取对应的键与对应的值。

public Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)

获取了Entry对象 , 表示获取了一对键和值,那么同样Entry中 , 分别提供了获取键和获取值的方法:

  • public K getKey():获取Entry对象中的键。
  • public V getValue():获取Entry对象中的值
  1. {
  2. //Map的遍历: 通过键找值
  3. Map<String, Integer> map = new HashMap<>();
  4. map.put("Bob", 90);
  5. map.put("Jake", 97);
  6. map.put("Rose", 98);
  7. map.put("David", 89);
  8. map.put("Swish", 70);
  9. Set<String> set = map.keySet();
  10. for (String temp : set){
  11. System.out.println(map.get(temp));
  12. }
  13. //Map的遍历: 通过键值对方式
  14. Set<Map.Entry<String, Integer>> set1 = map.entrySet();
  15. for (Map.Entry<String,Integer> temp : set1){
  16. //遍历map
  17. System.out.println(temp.getKey() + " " + temp.getValue());
  18. }
  19. }
4.3Map的分类

        Java中的Map接口及其常见实现类,包括HashMapTreeMapLinkedHashMap。

  1. HashMap:元素按照键是无序,不重复,无索引,值不做要求。存储数据采用的哈希表结构,元素的存取顺序不能保证一致由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
  2. LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求。HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
  3. TreeMap:元素按照键是排序,不重复,无索引的,值不做要求。底层的数据结构是红黑树;可以对元素的进行排序,排序方式有两种:自然排序比较器排序
5.1HashMap集合

        HashMap是Map的一个字类,so调Mao里面的方法就完事啦。!!!Why重写键的hashCode ()方法、equals()方法。去看看HashSet存放自定义对象相关问题。

        注意HashMap的特点:元素按照键是无序,不重复,无索引,值不做要求。

  1. package com.tsm.collection.map;
  2. import java.util.Objects;
  3. public class Student {
  4. private String name;
  5. private int age;
  6. public Student(String name, int age){
  7. this.age = age;
  8. this.name = name;
  9. }
  10. //构造方法
  11. //get/set
  12. @Override
  13. public boolean equals(Object o) {
  14. if (this == o)
  15. return true;
  16. if (o == null || getClass() != o.getClass())
  17. return false;
  18. Student student = (Student) o;
  19. return age == student.age && Objects.equals(name, student.name);
  20. }
  21. @Override
  22. public int hashCode() {
  23. return Objects.hash(name, age);
  24. }
  25. }
  1. package com.tsm.collection.map;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import java.util.Set;
  5. public class hashMap {
  6. public static void main(String[] args) {
  7. //1,创建Hashmap集合对象。
  8. Map<Student,String> map = new HashMap<Student,String>();
  9. //2,添加元素。
  10. map.put(new Student("lisi",28), "上海");
  11. map.put(new Student("wangwu",22), "北京");
  12. map.put(new Student("wangwu",22), "南京");
  13. //3,取出元素。键找值方式
  14. Set<Student> keySet = map.keySet();
  15. for(Student key: keySet) {
  16. String value = map.get(key);
  17. System.out.println(key.toString() + "....." + value);
  18. }
  19. }
  20. }
5.2LinkedHashMap集合

        如果要保证map中存放的key和取出的顺序一致,可以使用java.util.LinkedHashMap集合来存放。

  1. package com.tsm.collection.map;
  2. import java.util.LinkedHashMap;
  3. import java.util.Map;
  4. import java.util.Set;
  5. public class linkedHashMap {
  6. public static void main(String[] args) {
  7. //LinkedHashMap 按键有序!!!(键key存入和取出顺序是一样的)
  8. LinkedHashMap linkedHashMap = new LinkedHashMap();
  9. linkedHashMap.put("aaaaa", 123);
  10. linkedHashMap.put("bbbbb", 456);
  11. linkedHashMap.put("ddddd", 765);
  12. linkedHashMap.put("ccccc", 987);
  13. Set<Map.Entry<String,Integer>> set = linkedHashMap.entrySet();
  14. for (Map.Entry<String,Integer> entry : set){
  15. System.out.println(entry.getKey() + " " + entry.getValue());
  16. }
  17. }
  18. }

运行结果:

aaaaa   123
bbbbb   456
ddddd   765
ccccc   987

Process finished with exit code 0

小飞猪好睡好,长高高!!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/301250
推荐阅读
相关标签
  

闽ICP备14008679号