Java中的容器大杂烩-集合

news2024/11/14 19:06:31

Java中的容器大杂烩-集合

      • 一、 集合引入
      • 二、集合框架体系
      • 三 、Collection 接口
      • 四 、List集合
        • 4.1 `ArrayList`类
        • 4.2 `LinkedList`类
        • 4.3 `Vector`类
        • 4.4 `ArrayList `、 `LinkedList` 和 `Vector`区别
      • 五 、Set集合
        • 5.1 `HashSet`类
        • 5.2 `TreeSet`
        • 5.3 LinkedHashSet类
      • 六、List和Set区别
      • 七 、Map集合
        • 7.1 HashMap
        • 7.2 LinkedHashMap
        • 7.3 HashTable
        • 7.4 HashMap和HashTable比较
        • 7.5 TreeMap
      • 八 、Iterator 与 ListIterator
        • 8.1 `Iterator`
        • 8.2 `ListIterator`
      • 九、集合使用场景
        • 9.1 Collection接口选择
        • 9.2 Map接口选择
      • 十、阿里Java开发手册规约

一、 集合引入

在Java中,我们经常用到数组来存储数据。

但是数组的长度是不可变的,一旦在初始化数组时指定了数组长度,这个数组长度就是不可变的了。

而大多数实际应用中,数据的数量是没法确定的,并且有些数据具有一定映射关系。

比如学生身高 <张三—170>、<李四—160>、<王五—180>,这些数据就是有有映射关系的,需要保存这样有映射关系的数据,数组就有点无能为力了。

这时候就需要我们的集合出马了

集合就像书架、抽屉、购物袋、衣柜、保险柜这样存放物体的容器。

现实生活中,这样的容器很多,当然了在Java中集合的类型也很多,用来存放不同的对象,其功能也会有所不同。

有些方便存入和取出、有的具有排序功能、有的可以保证安全性等等

二、集合框架体系

集合主要由两大接口派生而来:

  • Collection 接口,主要用于存放单一元素;

  • Map接口,主要用于存放具有映射关系的数据,以键值对的形式进行存储

Collection 接口
image-20230418220637009
注意:以上图中只列举了主要的我们常接触继承派生关系,并没有列举所有关系。
黄色背景的为接口,其他背景的为实现类

接口名称接口作用
List 接口存储的元素是有序的、可重复的
Set 接口存储的元素是无序的、不可重复的
Queue 接口按特定的排队规则来确定先后顺序,存储的元素是有序的、可重复的
Map 接口使用键值对(key-value)存储,key 是无序的、不可重复的,value 是无序的、可重复的,每个键最多映射到一个值

三 、Collection 接口

Collection接口作为List Set Queue 的父接口,提供了一些“公共资产”(公共方法) 给实现类(List Set Queue)使用。

在这里插入图片描述

Collection既然作为父接口,一般不直接使用了,而是通过实现类来实现对集合的基本操作

接下来,我们以Collection 的实现类ArrayList 来具体演示一下集合的常用方法

①集合的基本操作

package com.xiezhr;

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

/**
 * @author xiezhr
 * @version 1.0
 * @description: TODO
 * @date 2023/4/15 17:07
 */
public class CollectionDemo {

    public static void main(String[] args) {
        List list = new ArrayList();

        //1 往list集合中添加元素
        list.add("xiezhr");
        list.add("xiezhrspace.cn");
        list.add(666);
        list.add(true);
        System.out.println("list中添加元素后list:"+list);

        // 2 获取list集合元素个数
        System.out.println("list集合元素个数:"+list.size());

        // 3 删除list中指定元素
        list.remove(0);
        list.remove(true);
        System.out.println("list中删除元素后list:"+list);

        // 4 查找指定元素是否存在
        System.out.println("查找list中是否存在xiezhrspace.cn  "+list.contains("xiezhrspace.cn"));

        // 5 判断list集合是否为空
        System.out.println("list集合是否为空"+list.isEmpty());

        // 6 清空list中所有元素
        list.clear();
        System.out.println("删除list集合中所有元素后list:" + list);

        // 7 往list中添加多个元素(直接将一个集合添加进去)
        List list2 = new ArrayList();
        list2.add("海贼王");
        list2.add("火影忍者");
        list2.add("名侦探柯南");

        list.add(list2);
        System.out.println("list2:" + list2);
        System.out.println("list集合中添加list2后list:" + list);

        // 8 查找多个元素是否存在
        System.out.println("list中是否存在list2中的元素"+list.containsAll(list2));

        // 9 删除多个元素

        list.removeAll(list2);

        list.add("画江湖之不良人");

        System.out.println("list:" + list);

    }
}
//
list中添加元素后list:[xiezhr, xiezhrspace.cn, 666, true]
list集合元素个数:4
list中删除元素后list:[xiezhrspace.cn, 666]
查找list中是否存在xiezhrspace.cn  true
list集合是否为空false
删除list集合中所有元素后list:[]
list2:[海贼王, 火影忍者, 名侦探柯南]
list集合中添加list2后list:[[海贼王, 火影忍者, 名侦探柯南]]
list中是否存在list2中的元素false
list:[[海贼王, 火影忍者, 名侦探柯南], 画江湖之不良人]

②使用Iterator(迭代器) 遍历集合

所有实现Collection接口的集合都有一个iterator()方法用于遍历集合

package com.xiezhr;

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

/**
 * @author xiezhr
 * @version 1.0
 * @description: TODO
 * @date 2023/4/15 17:07
 */
public class CollectionDemo {

    public static void main(String[] args) {
        List list = new ArrayList();

        // 往list集合中添加元素
        list.add("个人公众号:xiezhrspace");
        list.add("个人博客:www.xiezhrspace.cn");
        list.add(666);
        list.add(true);
        System.out.println("list中添加元素后list:"+list);

        //使用Iterator(迭代器)  遍历list集合

        //①得到list集合的迭代器iterator
        Iterator iterator = list.iterator();
        //②hasNext()用于判断是否还有下一个元素
        while (iterator.hasNext()){
            //③ 指针往后移动,将后移后集合上的元素返回
            System.out.println(iterator.next());
        }


    }
}
//执行结果
list中添加元素后list:[个人公众号:xiezhrspace, 个人博客:www.xiezhrspace.cn, 666, true]
个人公众号:xiezhrspace
个人博客:www.xiezhrspace.cn
666
true

image-20230415200108881

③使用for 循环增强 遍历集合

package com.xiezhr;

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

/**
 * @author xiezhr
 * @version 1.0
 * @description: TODO
 * @date 2023/4/15 17:07
 */
public class CollectionDemo {

    public static void main(String[] args) {
        List list = new ArrayList();

        // 往list集合中添加元素
        list.add("个人公众号:xiezhrspace");
        list.add("个人博客:www.xiezhrspace.cn");
        list.add(666);
        list.add(true);
        System.out.println("list中添加元素后list:"+list);

        //使用for循环增强 遍历list集合
        for (Object o : list) {
            System.out.println(o);
        }

       
    }
}
// 执行结果
list中添加元素后list:[个人公众号:xiezhrspace, 个人博客:www.xiezhrspace.cn, 666, true]
个人公众号:xiezhrspace
个人博客:www.xiezhrspace.cn
666
true

四 、List集合

List 集合简介

  • List集合是一个有序、可重复的集合
  • List集合中的每一个元素都有对应的顺序索引,默认按元素的添加顺序设置元素的索引,第一个添加到 List 集合中的元素的索引为 0,第二个为 1,依此类推
  • List 集合允许使用重复元素,可以通过索引来访问指定位置的集合元素
  • List 实现了 Collection 接口,它主要有两个常用的实现类:ArrayList 类和 LinkedList

4.1 ArrayList

ArrayList有两种常见的构造方法

  • ArrayList() 构造一个初始容量为十的空列表
  • ArrayList(Collection<? extends E> c) 构造一个包含指定集合的元素的列表。

ArrayList 类除了使用 Collection 接口的所有方法之外,还有其自己独特的方法

image-20230415201707136

实践操作

package com.xiezhr;

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

/**
 * @author xiezhr
 * @version 1.0
 * @description: TODO
 * @date 2023/4/15 17:07
 */
public class ArrayListDemo {

    public static void main(String[] args) {
        List list = new ArrayList();

        list.add("萧炎");
        list.add("美杜莎");
        list.add("纳兰嫣然");

        System.out.println("list原始值:" + list);

        // 1 在list索引为1 的地方插入一个元素
        list.add(1,"xiezhr");

        System.out.println("list在索引1处添加一个元素后:" + list);

        // 2 获取list索引为3的元素
        System.out.println(list.get(3));

        // 3 获取元素首次出现的位置
        System.out.println("返回第一次出现“美杜莎”元素的位置:"+list.indexOf("美杜莎"));

        // 4 获取元素最后一次出现的位置
        System.out.println("返回最后一次出现“美杜莎”元素的位置:"+list.lastIndexOf("美杜莎"));

        // 5 用指定元素替换list中指定位置的元素
        list.set(3,"小医仙");
        System.out.println("用“小医仙”替换list索引为3的元素后:" + list);

        // 6 返回list中从指定的 fromIndex (包括)到 toIndex之间的子集合
        List retlist = list.subList(0, 1);
        System.out.println("返回的子集合是:" + retlist);

        // 7 对list 内容进行排序
        List sortlist = new ArrayList();
        sortlist.add(34);
        sortlist.add(5);
        sortlist.add(56);
        sortlist.add(9);
        sortlist.add(-23);

        System.out.println("原始list元素:" + sortlist);
        sortlist.sort(Comparator.naturalOrder());
        System.out.println("排序后得list:" + sortlist);
    }
}

//结果
list原始值:[萧炎, 美杜莎, 纳兰嫣然]
list在索引1处添加一个元素后:[萧炎, xiezhr, 美杜莎, 纳兰嫣然]
纳兰嫣然
返回第一次出现“美杜莎”元素的位置:2
返回最后一次出现“美杜莎”元素的位置:2
用“小医仙”替换list索引为3的元素后:[萧炎, xiezhr, 美杜莎, 小医仙]
返回的子集合是:[萧炎]
原始list元素:[34, 5, 56, 9, -23]
排序后得list:[-23, 5, 9, 34, 56]

注意:

  • set(int index, Object element) 方法来改变 List 集合指定索引处的元素时,指定的索引必须是 List 集合的有效索引。当集合长度为 3,就不能指定替换索引为大于等于 处的元素,也就是说这个方法不会往list中添加新元素,只会替换原有元素
  • indexOf()方法和 lastIndexOf() 方法,前者是获得指定list的最小索引位置,而后者是获得指定list的最大索引位置。前提条件是指定的对象在 List 集合中有重复的对象,否则这两个方法获取的索引值相同
  • subList(1,3) 方法实际截取的是索引 1 到索引 2 的元素,并组成新的 List 集合

4.2 LinkedList

LinkedList类有两种构造方法

  • LinkedList() 构造一个空列表
  • LinkedList(Collection<? extends E> c) 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序

LinkedList 除了包含 Collection 接口中的所有方法之外,还有其自己独特的方法

image-20230415221411684

实践操作

package com.xiezhr;

import java.util.LinkedList;

/**
 * @author xiezhr
 * @version 1.0
 * @description: TODO
 * @date 2023/4/15 17:07
 */
public class LinkedListDemo {

    public static void main(String[] args) {
        LinkedList linkedList = new LinkedList();

        linkedList.add("海贼王");
        linkedList.add("火影忍者");


        System.out.println("linkedList原始值:" + linkedList);

        // 1 addFirst向集合开头插入一个元素
        linkedList.addFirst("名侦探柯南");
        System.out.println("linkedList使用addFirst开头插入一个值后:" + linkedList);

        // 2 addLast向集合末尾插入一个元素
        linkedList.addLast("忍者神龟");
        System.out.println("linkedList使用addLast末尾插入一个值后:" + linkedList);

        // 3 push向集合开头添加一个元素
        linkedList.push("鬼灭之刃");
        System.out.println("linkedList使用push在集合开头插入一个值后:" + linkedList);

        //4 offer向集合末尾插入一个元素
        linkedList.offer("灵笼");
        System.out.println("linkedList使用offer末尾插入一个值后:" + linkedList);

        // 5 add(int index,E element) 在指定位置插入元素
        linkedList.add(2,"无间道");
        System.out.println("linkedList在索引为2的位置插入一个值后:" + linkedList);

        // 6 offerLast 在末尾插入一个元素
        linkedList.offerLast("白蛇传");
        System.out.println("linkedList使用offerLast末尾插入一个值后:" + linkedList);

        // 7 offerFirst 在第一个位置插入一个元素
        linkedList.offerFirst("不良人");
        System.out.println("linkedList使用offerFirst开头插入一个值后:" + linkedList);

        // 8 按下标获取元素
        System.out.println("获取下标为2的元素"+linkedList.get(2));

        // 9 获取第一个元素
        System.out.println("获取集合的第一个元素为:" + linkedList.getFirst());

        // 10 获取最后一个元素
        System.out.println("获取集合最后一个元素为:" + linkedList.getLast());

        // 11 通过peek获取第一个元素,不删除元素
        System.out.println("使用peek()方法前:" + linkedList);
        System.out.println("通过peek()获取第一个元素为:" + linkedList.peek());
        System.out.println("使用peek()方法后:" + linkedList);

        // 12 通过peekFirst获取第一个元素,不删除元素
        System.out.println("使用peekFirst方法前:" + linkedList);
        System.out.println("通过peekFirst获取第一个元素为:" + linkedList.peekFirst());
        System.out.println("使用peekFirst方法后:" + linkedList);

        // 13 通过peekLast获取第一个元素,不删除元素
        System.out.println("使用peekLast方法前:" + linkedList);
        System.out.println("通过peekLast获取最后一个元素为:" + linkedList.peekLast());
        System.out.println("使用peekLast方法后:" + linkedList);

        // 14 通过poll 查询并删除第一个元素
        System.out.println("使用poll方法前:" + linkedList);
        System.out.println("通过poll获取第一个元素为:" + linkedList.poll());
        System.out.println("使用poll方法后:" + linkedList);

        // 15 通过pollFirst 查询并删除第一个元素
        System.out.println("使用pollFirst方法前:" + linkedList);
        System.out.println("通过pollFirst获取第一个元素为:" + linkedList.pollFirst());
        System.out.println("使用pollFirst方法后:" + linkedList);

        // 15 通过 pollLast 查询并删除最后元素
        System.out.println("使用pollLast方法前:" + linkedList);
        System.out.println("通过pollLast获取最后一个元素为:" + linkedList.pollLast());
        System.out.println("使用pollLast方法后:" + linkedList);

        // 16 删除集合第一个元素
        System.out.println("linkedList使用removeFirst方法前:" + linkedList);
        linkedList.removeFirst();
        System.out.println("linkedList删除第一个元素后:" + linkedList);

        // 17 删除集合最后一个元素
        System.out.println("linkedList使用removeLast方法前:" + linkedList);
        linkedList.removeLast();
        System.out.println("linkedList删除最后一个元素后:" + linkedList);

        // 18 remove(E e):移除指定元素
        System.out.println("linkedList使用remove方法前:" + linkedList);
        linkedList.remove("忍者神龟");
        System.out.println("linkedList删除指定元素后:" + linkedList);



    }
}
//结果
linkedList原始值:[海贼王, 火影忍者]
linkedList使用addFirst开头插入一个值后:[名侦探柯南, 海贼王, 火影忍者]
linkedList使用addLast末尾插入一个值后:[名侦探柯南, 海贼王, 火影忍者, 忍者神龟]
linkedList使用push在集合开头插入一个值后:[鬼灭之刃, 名侦探柯南, 海贼王, 火影忍者, 忍者神龟]
linkedList使用offer末尾插入一个值后:[鬼灭之刃, 名侦探柯南, 海贼王, 火影忍者, 忍者神龟, 灵笼]
linkedList在索引为2的位置插入一个值后:[鬼灭之刃, 名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼]
linkedList使用offerLast末尾插入一个值后:[鬼灭之刃, 名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼, 白蛇传]
linkedList使用offerFirst开头插入一个值后:[不良人, 鬼灭之刃, 名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼, 白蛇传]
获取下标为2的元素名侦探柯南
获取集合的第一个元素为:不良人
获取集合最后一个元素为:白蛇传
使用peek()方法前:[不良人, 鬼灭之刃, 名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼, 白蛇传]
通过peek()获取第一个元素为:不良人
使用peek()方法后:[不良人, 鬼灭之刃, 名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼, 白蛇传]
使用peekFirst方法前:[不良人, 鬼灭之刃, 名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼, 白蛇传]
通过peekFirst获取第一个元素为:不良人
使用peekFirst方法后:[不良人, 鬼灭之刃, 名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼, 白蛇传]
使用peekLast方法前:[不良人, 鬼灭之刃, 名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼, 白蛇传]
通过peekLast获取最后一个元素为:白蛇传
使用peekLast方法后:[不良人, 鬼灭之刃, 名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼, 白蛇传]
使用poll方法前:[不良人, 鬼灭之刃, 名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼, 白蛇传]
通过poll获取第一个元素为:不良人
使用poll方法后:[鬼灭之刃, 名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼, 白蛇传]
使用pollFirst方法前:[鬼灭之刃, 名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼, 白蛇传]
通过pollFirst获取第一个元素为:鬼灭之刃
使用pollFirst方法后:[名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼, 白蛇传]
使用pollLast方法前:[名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼, 白蛇传]
通过pollLast获取最后一个元素为:白蛇传
使用pollLast方法后:[名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼]
linkedList使用removeFirst方法前:[名侦探柯南, 无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼]
linkedList删除第一个元素后:[无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼]
linkedList使用removeLast方法前:[无间道, 海贼王, 火影忍者, 忍者神龟, 灵笼]
linkedList删除最后一个元素后:[无间道, 海贼王, 火影忍者, 忍者神龟]
linkedList使用remove方法前:[无间道, 海贼王, 火影忍者, 忍者神龟]
linkedList删除指定元素后:[无间道, 海贼王, 火影忍者]

4.3 Vector

VectorList 的古老实现类,底层使用Object[] 存储,线程安全的

4.4 ArrayList LinkedListVector区别

image-20230417221547510

  • ArrayListLinkedList 都是 List 接口的实现类
  • 实现List接口方式的不同,所以对不同的操作具有不同的效率
  • ArrayListLinkedList 都是不同步的,也就是不保证线程安全
  • ArrayList 底层使用的是 Object 数组LinkedList 底层使用的是 双向链表 数据结构
  • ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。 比如:执行add(E e)方法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是 O(1)。但是如果要在指定位置 i 插入和删除元素的话(add(int index, E element))时间复杂度就为 O(n-i)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作
  • LinkedList 采用链表存储,所以,如果是在头尾插入或者删除元素不受元素位置的影响(add(E e)addFirst(E e)addLast(E e)removeFirst()removeLast()),时间复杂度为 O(1),如果是要在指定位置 i 插入和删除元素的话(add(int index, E element)remove(Object o)), 时间复杂度为 O(n) ,因为需要先移动到指定位置再插入
  • LinkedList 不支持高效的随机元素访问,而 ArrayList 支持,通过get(int index) set(int index) 可以快速获取元素,修改元素
  • 创建ArrayList 会在结尾预留一定容量的空间,而LinkedList 占用的空间比ArrayList 更多(空间除了存储数据之外还需要存储直接后继和直接前驱
  • 如果需要经常插入、删除操作来改变List集合的大小,则应该使用LinkedList集合

五 、Set集合

  • 没有顺序(添加和取出元素的顺序不一致),没有索引
  • 添加的元素不允许重复,最多只能包含一个null
  • 主要有两个常用的实现类:HashSet 类和 TreeSet类

①实践操作

由于Set 属于接口,我们以Set 接口的实现类HashSet 来演示

package com.xiezhr;

import java.util.HashSet;

/**
 * @author xiezhr
 * @version 1.0
 * @description: TODO
 * @date 2023/4/15 17:07
 */
public class SetDemo {

    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        hashSet.add("海贼王");
        System.out.println(hashSet.add("海贼王"));
        System.out.println("set添加元素后结果" + hashSet);
    }
}
// 结果
false
set添加元素后结果[海贼王]

从上面示例中,我们发现往set集合中添加重复元素是不允许的

5.1 HashSet

  • HashSetSet 接口的典型实现,大多数时候使用 Set 集合时就是使用这个实现类

  • HashSet 是按照 Hash 算法来存储集合中的元素。因此具有很好的存取和查找性能

  • 不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化

  • HashSet 不是同步的,如果多个线程同时访问或修改一个 HashSet,则必须通过代码来保证其同步

  • 集合元素值可以是 null

  • 当向HashSet 集合中存入一个元素时,HashSet会通过获取元素的hashcode 值来确定元素在HashSet集合中的存储位置。如果两个元素equale比较为true但是hashcode不相等,这两个元素也被当作时不同的元素,存储在不同的位置

HashSet 有常见的两种构造方法

  • HashSet() 构造一个新的空集合
  • HashSet(Collection<? extends E> c) 构造一个包含指定集合中的元素的新集合

实践操作,用HashSet 创建一个,并向集合中添加几个动漫,并通过不同方式遍历集合

package com.xiezhr;

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

/**
 * @author xiezhr
 * @version 1.0
 * @description: TODO
 * @date 2023/4/15 17:07
 */
public class SetDemo {

    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        hashSet.add("海贼王");
        hashSet.add("火影忍者");
        hashSet.add("鬼灭之刃");
        hashSet.add("间谍过家家");

        System.out.println("hashSet添加元素后:" + hashSet);

        //1 通过过滤器 Iterator 遍历集合
        System.out.println("------------------通过过滤器 Iterator 遍历hashSet集合-------------------------");
        Iterator iterator = hashSet.iterator();

        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        // 2 通过增强for循环遍历
        System.out.println("------------------通过增强for循环 遍历hashSet集合-------------------------");
        for (Object o : hashSet) {
            System.out.println(o);
        }
    }
}
//执行结果
hashSet添加元素后:[火影忍者, 间谍过家家, 鬼灭之刃, 海贼王]
------------------通过过滤器 Iterator 遍历hashSet集合-------------------------
火影忍者
间谍过家家
鬼灭之刃
海贼王
------------------通过增强for循环 遍历hashSet集合-------------------------
火影忍者
间谍过家家
鬼灭之刃
海贼王

5.2 TreeSet

  • TreeSet 类同时实现了 Set 接口和 SortedSet 接口。使用 TreeSet 类实现的 Set 接口默认情况下是自然排序的,这里的自然排序指的是升序排序
  • TreeSet 只能对实现了 Comparable 接口的类对象进行排序

TreeSet 类除了实现 Collection 接口的所有方法之外

image-20230416172114407

实践操作:我们将一组学生的成绩【68.0,50.5,78.6,88.0,95.0,45.5】 存入TreeSet,并进行TreeSet 集合的基本操作演示

package com.xiezhr;

import java.util.*;

/**
 * @author xiezhr
 * @version 1.0
 * @description: TODO
 * @date 2023/4/15 17:07
 */
public class TreeSetDemo {

    public static void main(String[] args) {
        TreeSet<Double> scoreSet = new TreeSet<Double>();

        scoreSet.add(68.0);
        scoreSet.add(50.5);
        scoreSet.add(78.6);
        scoreSet.add(88.0);
        scoreSet.add(95.0);
        scoreSet.add(45.5);

        System.out.println("添加分数后的scoreSet:" + scoreSet);
        // 1 学生分数由低到高排序
        Iterator<Double> it = scoreSet.iterator(); // 创建 Iterator 对象
        System.out.println("学生分数从低到高的排序为:");
        while (it.hasNext()) {
            System.out.print(it.next() + "\t");
        }

        // 2 查找分数为90分的是否存在
        if (scoreSet.contains(90.0)) {
            System.out.println("成绩为: " + 90.0 + " 存在!");
        } else {
            System.out.println("成绩为: " + 90.0 + " 不存在!");
        }

        // 3 查找不及格分数
        System.out.println("\n不及格的有:");
        SortedSet<Double> score1 = scoreSet.headSet(60.0);
        for (int i = 0; i < score1.toArray().length; i++) {
            System.out.print(score1.toArray()[i] + "\t");
        }

        // 4 查找90分以上分数
        System.out.println("\n90 分以上的有:");
        SortedSet<Double> score2 = scoreSet.tailSet(90.0);
        for (int i = 0; i < score2.toArray().length; i++) {
            System.out.print(score2.toArray()[i] + "\t");
        }

    }
}
//执行结果
添加分数后的scoreSet:[45.5, 50.5, 68.0, 78.6, 88.0, 95.0]
学生分数从低到高的排序为:
45.5	50.5	68.0	78.6	88.0	95.0	成绩为: 90.0 不存在!

不及格的有:
45.5	50.5	
90 分以上的有:
95.0	

5.3 LinkedHashSet类

LinkedHashSet: LinkedHashSetHashSet 的子类,并且其内部是通过 LinkedHashMap 来实现的。有点类似于我们之前说的 LinkedHashMap 其内部是基于 HashMap 实现一样,不过还是有一点点区别

六、List和Set区别

image-20230417214245733

七 、Map集合

  • Map 是一种键-值对(key-value)集合,Map 集合中的每一个元素都包含一个键(key)对象和一个值(value)对象
  • Map 用于保存具有映射关系的数据
  • keyvalue都可以是任何引用类型的数据
  • Mapkey 不允许重复,value 可以重复
  • Map 中的 keyvalue 之间存在单向一对一关系,即通过指定的 key,总能找到唯一的、确定的 value
  • Map 接口主要有两个实现类:HashMap 类和 TreeMap 类。其中,HashMap 类按哈希算法来存取键对象,而 TreeMap 类可以对键对象进行排序

Map 常用方法

image-20230417204552991

7.1 HashMap

  • Hashmap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度
  • 遍历时,取得数据的顺序是完全随机的
  • HashMap最多只允许**一条记录的键为Null;**允许多条记录的值为Null
  • HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用Collections的synchronizedMap方法使HashMap具有同步的能力

7.2 LinkedHashMap

  • 保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录是先插入的,也可以在构造时用带参数,按照应用次数排序,需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现
  • 遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢

7.3 HashTable

  • Hashtable 与 HashMap类似,不同的是:它不允许记录的键或者值为空
  • 支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢

7.4 HashMap和HashTable比较

image-20230418231752235

7.5 TreeMap

  • TreeMap实现SortMap接口,内部实现是红黑树
  • 能够把它保存的记录根据键排序默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的
  • TreeMap不允许key的值为null。非同步的

TreeMap 除了具有Map通用方法之外,还有自己特殊的方法

image-20230418235231297

八 、Iterator 与 ListIterator

8.1 Iterator

Iterator是一个接口,它是集合的迭代器。在前面的示例中我们已经使用过,集合可以通过Iterator去遍历集合中的元素

Iterator 常用的API主要有以下几类

boolean hasNext()判断集合里是否存在下一个元素。如果有,hasNext()方法返回 true
Object next()返回集合里下一个元素
void remove()删除集合里上一次next方法返回的元素
package com.xiezhr;

import java.util.*;

/**
 * @author xiezhr
 * @version 1.0
 * @description: TODO
 * @date 2023/4/15 17:07
 */
public class IteratorDemo {

    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("西游记");
        arrayList.add("红楼梦");
        arrayList.add("三国演义");
        arrayList.add("水浒传");

        System.out.println("添加元素后arrayList:" + arrayList);

        Iterator<String> iterator = arrayList.iterator();
        while (iterator.hasNext()){
            String book = iterator.next();
            if("红楼梦".equals(book)){
                iterator.remove();
            }
        }

        System.out.println("删除红楼梦后arrayList:" + arrayList);


    }
}
//执行结果
添加元素后arrayList:[西游记, 红楼梦, 三国演义, 水浒传]
删除红楼梦后arrayList:[西游记, 三国演义, 水浒传]

注意:

  • Iterator只能单向移动

  • Iterator.remove()是唯一安全的方式来在迭代过程中修改集合;如果在迭代过程中以任何其它的方式修改了基本集合将会产生未知的行为。而且每调用一次next()方法,remove()方法只能被调用一次,如果违反这个规则将抛出一个异常

8.2 ListIterator

  • ListIterator是一个功能更加强大的迭代器, 它继承于Iterator接口,只能用于各种List类型的访问
  • 可以通过调用listIterator()方法产生一个指向List开始处的ListIterator
  • 还可以调用listIterator(n)方法创建一个一开始就指向列表索引为n的元素处的ListIterator
  • 可以双向移动(向前/向后遍历)
  • 可以使用set()方法替换它访问过的最后一个元素
  • 可以使用add()方法在next()方法返回的元素之前或previous()方法返回的元素之后插入一个元素
package com.xiezhr;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;

/**
 * @author xiezhr
 * @version 1.0
 * @description: TODO
 * @date 2023/4/15 17:07
 */
public class ListIteratorDemo {

    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<String>();
        arrayList.add("西游记");
        arrayList.add("红楼梦");
        arrayList.add("三国演义");
        arrayList.add("水浒传");

        System.out.println("arrayList添加元素后 : " + arrayList);
        ListIterator<String> it = arrayList.listIterator();

        // 1 获取前后索引和当前值
        System.out.println("-------------------获取前后索引和当前值--------------------");
        while (it.hasNext()) {
            System.out.println(it.next() + ", " + it.previousIndex() + ", " + it.nextIndex());
        }

        // 2 从后向前遍历
        System.out.println("-----------------------从后向前遍历-----------------------");
        while (it.hasPrevious()) {
            System.out.print(it.previous() + " ");
        }

        System.out.println();
        // 3 从指定索引开始遍历
        System.out.println("------------------从指定索引开始遍历---------------------");
        it = arrayList.listIterator(2);  //从索引2 开始遍历


        while (it.hasNext()) {
            String t = it.next();
            System.out.println(t);
            // 4 迭代过程中修改集合
            if ("三国演义".equals(t)) {
                it.set("少年包青天");
            } else {
                it.add("xiezhr");
            }
        }
        System.out.println("操作后的arrayList : " + arrayList);
    }

}
//执行结果
arrayList添加元素后 : [西游记, 红楼梦, 三国演义, 水浒传]
-------------------获取前后索引和当前值--------------------
西游记, 0, 1
红楼梦, 1, 2
三国演义, 2, 3
水浒传, 3, 4
-----------------------从后向前遍历-----------------------
水浒传 三国演义 红楼梦 西游记 
------------------从指定索引开始遍历---------------------
三国演义
水浒传
操作后的arrayList : [西游记, 红楼梦, 少年包青天, 水浒传, xiezhr]

九、集合使用场景

既然有这么多类型的集合供我们使用,那么我们应该怎么选择呢?

9.1 Collection接口选择

在这里插入图片描述

9.2 Map接口选择

image-20230419212229637

示例:

package com.xiezhr;

import java.util.*;

/**
 * @author xiezhr
 * @version 1.0
 * @description: TODO
 * @date 2023/4/15 17:07
 */
public class MapDemo {

    public static void main(String[] args) {
      //1 使用HashMap
        HashMap<String,String> hashMap = new HashMap<>();
        hashMap.put("4","d");
        hashMap.put("3","c");
        hashMap.put("2","b");
        hashMap.put("1","a");

        Iterator<String> iteratorHashMap = hashMap.keySet().iterator();

        System.out.println("----------------------HashMap--------------------------");
        while (iteratorHashMap.hasNext()){
            Object key1 = iteratorHashMap.next();
            System.out.println(key1 + "--" + hashMap.get(key1));
        }

        System.out.println("----------------------LinkedHashMap--------------------------");
        // 2 使用LinkedHashMap
        LinkedHashMap<String,String> linkedHashMap = new LinkedHashMap<>();
        linkedHashMap.put("4","d");
        linkedHashMap.put("3","c");
        linkedHashMap.put("2","b");
        linkedHashMap.put("1","a");

        Iterator<String> iteratorlinkedHashMap = linkedHashMap.keySet().iterator();

        while (iteratorlinkedHashMap.hasNext()){
            String key2 = iteratorlinkedHashMap.next();
            System.out.println(key2 + "--" + linkedHashMap.get(key2));
        }

        // 3 使用TreeMap
        TreeMap<String,String> treeMap = new TreeMap<>();
        treeMap.put("4","d");
        treeMap.put("3","c");
        treeMap.put("2","b");
        treeMap.put("1","a");

        Iterator<String> iteratorTreeMap = treeMap.keySet().iterator();

        System.out.println("----------------------treeMap--------------------------");
        while (iteratorTreeMap.hasNext()){
            String key3 = iteratorTreeMap.next();
            System.out.println(key3 + "--" + treeMap.get(key3));
        }


    }
}
//执行结果
----------------------HashMap--------------------------
1--a
2--b
3--c
4--d
----------------------LinkedHashMap--------------------------
4--d
3--c
2--b
1--a
----------------------treeMap--------------------------
1--a
2--b
3--c
4--d

十、阿里Java开发手册规约

❶**【强制】** 关于hashCodeequals的处理,遵循如下规则

1)只要复写equals,就必须覆写hashCode

2)因为Set存储的是不重复的对象,所以以及hashCodeequals进行判断,Set存储的对象必须覆写这两种方法

3)如果自定义对象作为Map的键,那么必须覆写hashCodeequals

说明:String因为覆写了hashCode和equals方法,所以可以愉快的将对象作为key使用

❷**【强制】** 判断所有集合内部元素是否为空,应该用isEmpty()方法,而不是使用size()==0的方式

说明:在某些集合中,前者的时间复杂度为O(1),可读性更好

正例:

Map<String,Object> map = new HashMap<>(16);
if(map.isEmpty()){
    System.out.println("no element in this map.")
}

❸**【强制】** 在使用 java.util.stream.Collectors类的toMap()方法转为Map集合时,一定要使用含以后参数类型为BinaryOperator、参数名为mergeFunction的方法,否则出现相同 key值时,会抛出IllegalStateException异常。

说明: 参数mergeFunction 的作用是当出现key重复时,自定义对value的处理策略。

正例:

List<Pair<String,Double>> pairArrayList = new ArrayList<>(3);
pairArrayList.add(new Pair<>("version",6.19));
pairArrayList.add(new Pair<>("version",10.24));
pairArrayList.add(new Pair<>("version",13.14));
//在生成的Map集合中,只有一个键值对:{version=13.14}
Map<String,Double> map = pairArrayList.stream().collect(Collectors.toMap(Pair::getKey,pair::getValue,(v1,v2)->v2));

反例:

String[] words = new String[]{"w","w","x"}
//抛出IllegStateException 异常
Map<Integer,String> map = Arrays.stream(words).collect(Collectors.toMap(String::hashCode,v->v))

❹**【强制】** 在使用java.util.stream.Collectors 类的toMap()方法转为Map集合时,一定要注意当valuenull时,会抛出异常。

说明: 在java.util.HashMapmerge方法中,会进行如下判断:

if(value == null ||remappingFunction ==null)

throw new NullPointerException();

反例:

List<Pair<String,Double>> pairArrayList = new ArrayList<>(2);
pairArrayList.add(new Pair<>("version1",4.22));
pairArrayList.add(new Pair<>("version2",null));
Map<String,Double> map = pairArrayList.stream().collect(
	//抛出异常
    Collectors.toMap(Pair::getKey,Pair::getValue,(v1,v2)->v2);
)

❺**【强制】** ArrayListsubList结果不可强转成ArrayList,否则会抛出ClassCastException异常,即java.util.RandomAccessSubList canot be cast to java.util.ArrayList.

说明:subList() 返回的时ArrayList的内部类SubList,并不是ArrayList本身,而是ArrayList的一个试图,对应SubList的所有操作最终会反映到原列表上

❻**【强制】** 使用Map的方法keySet()/values()/entrySet()返回集合对象时,不可以对其添加元素,否则会抛出UnsupportedOperationException异常

❼**【强制】** Collections类返回的对象,如:emptyList()/singletonList() 等都是immutable list,不可对其添加或者删除元素。

反例:

如果查询无结果,返回Collections.emptyList()空集合对象,调用方一旦进行了添加元素的操作,就会触发UnsupportedOperationException异常

❽**【强制】** 在subList场景中,高度注意对父集合元素的增加火删除,它们均会导致子列表的遍历、增加、删除产生ConcurrentModificationException异常。

❾**【强制】** 使用集合转数组的方法,必须使用集合的toArray(T[] array),传入的是类型完全一致、长度为0的空数组。

反例:

直接使用toArray无参方法存在问题,此方法返回值只能是Object[] 类,若强转成其他类型数组,将出现ClassCastException 异常

正例:

List<String> list = new ArrayList<>(2);
list.add("guan");
list.add("bao");
String [] array = list.toArray(new String[0]);

说明: 使用toArray带参方法,数组空间大小为length

1)等于0,动态创建于size相同的数组,性能最好

2) 大于0但小于size,重新创建大小等于size的数组,增加GC负担

3)等于size,在高并发情况下,在数组创建完成之后,size正在变大的情况下,负面影响与第二条相同

4)大于size,空间浪费,且在size处插入null值,存在NPE隐患

❿**【强制】** 在使用Collection接口任何实现类的addAll()方法时,都要对输入的集合参数进行NPE判断。

说明:ArrayList#addAll方法的第一行代码即Object[] a = c.toArray();

其中,c为输入集合参数,如果为null,则直接抛出异常

【强制】 当使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear方法会抛出UnsupporedOperationException异常。

说明:asList的返回对象时一个Arrays内部类,并没有实现集合的修改方法。Arrays.asList体现的时适配器模式,知识转换接口,后台的数据认识数组。

String[] str = new String[] {"yang",“hao”};

List list =Arrays.asList(str);

第一种情况:list.add("yangguanbao");运行时异常。

第二种情况:str[0] = "changed"; 也会随之修改,反之亦然

【强制】 泛型通配符<? extends T> 用来接收返回的数据,此写法的泛型集合不能使用add方法,而<? supper T> 不能使用get方法,因为两者在接口调用赋值的场景中容易出错。

说明: 扩展介绍一下PECS(Producer Extends Consumer Super)

​ 原则:第一,频繁往外读取内容的,适合用<? extends T> ;

​ 第二,经常往里插入的,适合用<? super T>

⓭**【强制】** 在无泛型限制定义的集合赋值给泛型限制的集合中,当使用集合元素时,需要镜像instanceof判断,避免抛出ClassCastException异常。

说明:比较泛型是在JDK5后才出现的,考虑到向前兼容,编译器允许非泛型集合与泛型集合相互赋值。

反例:

	List<String> generics = null;
	List notGenerics = new ArrayList(10);
	notGenerics.add(new Object());
	notGenerics.add(new Integer(1));
	generics = notGenerics;
	//此处抛出 ClassCastException 异常
	String string = generics.get(0);

【强制】 不要再foreach循环中对元素进行remove/add操作。当进行remove操作时,请使用Iterator方式。如果时并发操作,需要对Iterator对象加锁。

正例:

List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
    String item = iterator.next();
    if(删除元素条件){
        iterator.remove();
    }
}

反例:

for(String item : list){
    if("1".equals(item)){
        list.remove(item);
    }
}

说明:执行结果肯定会出乎大家的意料,试一下把“1”换成“2”,会是同样的结果吗?

【强制】 再JDK7及以上版本中,Comparator实现类要满足三个条件,否则Arrays.sortCollections.sort 会抛出IllegalArgumentException异常。

说明: 三个条件如下

​ 1)x,y的比较结果和y,x的比较结果相反。

​ 2)若x>y,y>z , 则x>z。

​ 3)若x=y,则x,z的比较结果和y,z的比较结果相同。

反例:下列中没有处理相等的情况,交换两个对象判断结果并不相反,不符合第一个条件,在实际使用中可能会出现异常

new Comparator<Student>(){
    @Override
    public int compare(Student o1,Student o2){
        return o1.getId()>o2.getId() ? 1:-1;
    }
}

【推荐】 当使用泛型集合定义时,在 JDK7及以上版本中,使用diamond语法或全省略。

说明: 菱形泛型即diamond,直接使用<>指代前边已经指定的类型

⓱**【推荐】** 当集合初始化时,指定集合初始值大小

说明: HashMap 使用HashMap(int initialCapacity) 初始化,如果暂时无法确定集合大小,那么指定默认值(16)即可。

正例:initialCapacity =(需要存储的元素个数/负载因子)+1.

​ 注意负载因子(即 loader factor)默认为0.75,如果暂时无法确定初始值大小,则设置为16(即默认值)。

反例:HashMap 需要放置1024 个元素,由于没有设置容量初始大小,则随着元素的增加而被迫不断扩容,resize()方法一给一共会调用8次,反复重建哈希表和数据迁移。当放置的集合元素规模达到千万时,会影响程序性能

⓲ 【推荐】使用entrySet 遍历Map类集合K/V,而不是用keySet方式遍历。

说明: keySet 方式其实遍历了两次,一次时转为Iterator对象,另一次时从hashMap中取出Key所对应的Value。而entrySet只遍历了一次九八KeyValue都放到了entery中,效率更高。如果是JDK8、则使用Map.forEach方法。

正例: values()返回的V值集合,是一个list集合对象;keySet()返回的是K值集合,是一个Set集合对象;entrySet()返回的是K-V值组合集合。

【推荐】 高度注意Map类集合K/V能否存储null值,如表1-1所示。

​ 表1-1 Map类集合K/V存储

集合类KeyValueSuper说明
Hashtable不允许为null不允许为nullDictionary线程安全
Concurrent HashMap不允许为null不允许为nullAbstractMap锁分段技术
TreeMap不允许为null允许为nullAbstractMap线程不安全
HashMap允许为null允许为nullAbstractMap线程不安全

反例:由于HashMap的干扰,很多人认为ConcurrentHashMap可以置入null值,而事实上,在存储null值时,会抛出NPE异常。

【参考】 合理利用好集合的有序性(sort)和稳定性(order),避免集合的无序性(unsort)和不稳定性(unorder)带来的负面影响。

说明:有序性指遍历的结果按某中比较规则依次排列。稳定性指集合每次遍历的元素次序时一定的。如:ArrayListorder/unsort;

HashMapunorder/unsort; TreeSetorder/sort

以上就是本期全部内容,希望对你有所帮助,我们下期再见 (●’◡’●)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/453084.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

制造业巨头遭黑客勒索400万美元,企业如何防范勒索病毒攻击?

4月7日&#xff0c;台湾电脑制造商微星&#xff08;简称MSI&#xff09;发布公开声明&#xff0c;证实其部分网络信息系统遭受了勒索病毒攻击。一个名为“Money Message”的新网络黑客团伙称其从微星的网络系统中窃取了1.5TB的数据&#xff0c;其中包括微星数据库的屏幕截图、源…

YAML /Excel /CSV?自动化测试测试数据管理应用,测试老鸟总结...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 自动化测试无论是…

webhub123 前端技术社区和技术交流学习网站导航

整理了学习前端技术可以参考学习和技术交流的一些网站集合&#xff0c;全部收录到 webhub123 前端技术社区和技术交流学习网站导航http://​www.webhub123.com/#/home/detail?projectHashid30929575&ownerUserid22053727 整理后的效果如下&#xff0c;我们已经按照不同类…

React Props

state 和 props 主要的区别在于 props 是不可变的&#xff0c;而 state 可以根据与用户交互来改变。 所以&#xff0c;有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。 props 使用 Demo.js &#xff1a; import React from reactfunct…

智能学习 | MATLAB实现ACO-BP多变量时间序列预测(蚁群算法优化BP神经网络)

智能学习 | MATLAB实现ACO-BP多变量时间序列预测(蚁群算法优化BP神经网络) 目录 智能学习 | MATLAB实现ACO-BP多变量时间序列预测(蚁群算法优化BP神经网络)预测效果基本介绍程序设计参考资料预测效果 基本介绍 MATLAB实现ACO-BP多变量时间序列预测(蚁群算法优化BP神经网络…

数据集合注入

集合注入 前面我们已经能完成引入数据类型和简单数据类型的注入&#xff0c;但是还有一种数据类型集合&#xff0c;集合中既可 以装简单数据类型也可以装引用数据类型&#xff0c;对于集合&#xff0c;在Spring中该如何注入呢? 先来回顾下&#xff0c;常见的集合类型有哪些…

Vue电商项目--应用开发详解

vue-cli脚手架初始化项目 首先&#xff0c;页面上新建一个文件夹。然后打开命令端口 vue create app 选择Default ([Vue 2] babel, eslint) 然后把项目拖拽到vscode中。项目目录看一下 脚手架项目的目录 node_modules:放置项目依赖的地方 public:一般放置一些共用的静态资源&a…

数据采集方式有哪些,都有什么特点?

随着中国社会的进一步发展&#xff0c;各行各业都得到了一定程度的进步。进入21世纪以来&#xff0c;大数据、人工智能等行业的飞速发展&#xff0c;极大的带动全社会进步。但是&#xff0c;在一些传统行业内部&#xff0c;还存在这落后的东西&#xff0c;例如数据采集还是沿用…

【机器学习】P24 随机森林算法(1) 实现 “鸢尾花” 预测

随机森林算法 Random Forest Algorithm 随机森林算法随机森林算法实现分类鸢尾花 随机森林算法 随机森林&#xff08;Random Forest&#xff09;算法 是一种 集成学习&#xff08;Ensemble Learning&#xff09;方法&#xff0c;它由多个决策树组成&#xff0c;是一种分类、回…

OS实战笔记(8)-- 设置基本OS基本工作环境

本笔记会搭建OS实战所需的虚拟机环境&#xff0c;主要是创建好虚拟机&#xff0c;设置虚拟机启动硬盘&#xff0c;在启动盘上安装Grub。 由于本专题是个人在业余时间除了Unity学习之外做的&#xff0c;没有时间和精力去解答具体的问题。本笔记中的实验个人在做的过程中除了遇到…

17.集合

集合 集合类是Java数据结构的实现。Java的集合类是java.util包中的重要内容&#xff0c;它允许以各种方式将元素分组&#xff0c;并定义了各种使这些元素更容易操作的方法。Java集合类是Java将一些基本的和使用频率极高的基础类进行封装和增强后再以一个类的形式提供。集合类是…

整理现有的wiki私服项目

文章目录 核心功能现有项目wikijsBookStackmediawikiTiddlyWikigollumdokuwikixwiki 总结参考 核心功能 查找编辑 在线/离线内链【核心】代码高亮图表、表达式生成多媒体&#xff08;图片、音频、视频&#xff09;管理 协作&#xff08;用户管理模式/github模式&#xff09; 修…

JVM 关键点详解

一&#xff0c;JVM 的主要组成部分及其作用 JVM包含两个子系统和两个组件&#xff0c;两个子系统为Class loader(类装载)、Execution engine(执行引擎); 两个组件为Runtime data area(运行时数据区)、Native Interface(本地接口)。 Class loader(类装载): 根据给定的全限定名类…

【Linux网络】部署YUM仓库及NFS服务

部署YUM仓库及NSF服务 一、YUM仓库1.1、YUM仓库概述1.2准备安装来源1.3在软件仓库加载非官方RPM包组1.4yum与apt 二、配置yam源与制作索引表2.1配置FTP源2.2配置国内在线yum源2.3在线源与本地源同时使用2.4建立软件包索引关系表的三种方法 三、nfs共享存储服务3.1安装软件&…

LVS负载均衡群集——NAT模式实操

1.1 群集的的定义及意义 群集的定义 Cluster&#xff0c;集群&#xff08;也称群集&#xff09;由多台主机构成&#xff0c;但对外只表现为一一个整体&#xff0c;只提供一-个访问入口(域名或IP地址)&#xff0c; 相当于一台大型计算机。 群集的作用 对于企业服务的的性能提升…

数学知识四

容斥原理 S表示面积&#xff0c;下面公式可求出不相交的面积 2个圆的公式是这样 4个圆的面积是 总面积-所有俩俩相交的面积所有三三相交的面积-四四相交的面积&#xff0c;公式里加和减互相出现。 从n个集合里面挑一个一直到从n个集合里面挑n个 1-10中&#xff0c;能被2&#x…

【KingSCADA】如何创建新应用

大家好&#xff0c;我是雷工! 今天学习使用KingSCADA3.8创建一个新的应用&#xff0c;以下为学习过程和操作笔记。 一、前言 KingSCADA3.8集成开发环境是基于工程的应用管理模式&#xff0c;实现了对多个应用的集中开发和管理的功能&#xff0c;一个工程可以同时管理多个应用…

【WinForm】Android手机群控工具-桌面程序开发实现

如何将手下多个Android手机统一管理起来呢&#xff0c;这里是用通过终端输入adb命令来实现控制多个手机的&#xff0c;具体怎么做&#xff0c;接下来给讲一讲。 使用adb工具包 首先&#xff0c;需要准备一套工具&#xff0c;以下是adb工具套件&#xff0c;是在Android SDK开发…

lanuage-driven semantic segmentation

CLIP 改进工作串讲&#xff08;上&#xff09;【论文精读42】_哔哩哔哩_bilibili更多论文&#xff1a;https://github.com/mli/paper-reading, 视频播放量 64310、弹幕量 274、点赞数 1939、投硬币枚数 1332、收藏人数 821、转发人数 438, 视频作者 跟李沐学AI, 作者简介 &…

window安装cplex20.1.0启动报错: ilog.odms.ide.opllang.IloOplLangPlugin

通过0-1背包问题看穷举法、贪心算法、启发式算法&#xff08;JAVA) 模拟退火(SA)算法实例介绍&#xff08;JAVA) 遗传算法&#xff08;GA&#xff09;实例介绍&#xff08;JAVA) CPLEX求解器入门案例 java集成Cplex&#xff1a;Cplex下载、IDEA环境搭建、docker部署 windo…