43、集合的第一大类:Set

news2025/8/9 2:17:40

一、基本介绍: 

1、Set接口的特点:

1)无序(添加和取出的顺序不一致) ,没有索引

2)不允许重复元素,所以最多包含一个null

3) JDK API中Set接口的实现类有:

 2、Set接口的常用方法:

和List接口一样,Set接口也是Collection的子接口,因此,常用方法和Collection接口一样.

3、Set接口的遍历方式:

同Collection的遍历方式一样,因为Set接口是Collection接口的子接口。

(1)可以使用迭代器

(2)增强for

(3)不能使用索引的方式来获取.

package Collection_;

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

public class SetMethod {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        Set set=new HashSet();
        set.add("john");
        set.add("lucky");
        set.add("john");
        set.add("jack");
        set.add(null);
        set.add(null);
        System.out.println("set="+set);
        //set=[lucky, null, john, jack]
        //取出的顺序是固定的,不会说同样的代码每次输出都不一样

        set.add("smith");
        System.out.println("set="+set);
        //set=[lucky, null, smith, john, jack]

        //遍历
        //1、使用迭代器
        System.out.println("=========使用迭代器=========");
        Iterator iterator=set.iterator();
        while (iterator.hasNext()) {
            Object obj =  iterator.next();
            System.out.println("obj="+obj);
        }

        //2、增强for
        System.out.println("=========增强for=========");
        for (Object o :set) {
            System.out.println("o="+o);
        }

    }
}
//=========使用迭代器=========
//obj=lucky
//obj=null
//obj=smith
//obj=john
//obj=jack
//=========增强for=========
//o=lucky
//o=null
//o=smith
//o=john
//o=jack

4、Set接口常用的实现类:有HashSet、TreeSet.

二、HashSet:

1、基本介绍: 

(1) HashSet实现了Set接口

(2)HashSet底层实际上是HashMap, 看下源码.

public HashSet(){
        map = new HashMap<>();
}

(3) 可以存放null值,但是只能有一个null.

(4)HashSet不保证元素是有序的,取决于hash后,再确定索引的结果.即,不保证存放元素的顺序和取出顺序一致

(5) 不能有重复元素/对象.

package Collection_;

import java.util.HashSet;
import java.util.Set;
@SuppressWarnings({"all"})
public class HashSet_ {
    public static void main(String[] args) {
        Set hashSet = new HashSet();
        hashSet.add(null);
        hashSet.add(null);
        System.out.println("hashset="+hashSet);
        //hashset=[null]
    }
}
package Collection_;

import java.util.HashSet;
import java.util.Set;
@SuppressWarnings({"all"})
public class HashSet_ {
    public static void main(String[] args) {
        Set set=new HashSet();
        set.add("john");
        set.add("tom");


        set =new HashSet();
        System.out.println("set="+set);//set=[]
        set.add("lucy");//ok
        set.add("lucy");//no
        set.add(new Dog("tom"));//ok
        set.add(new Dog("tom"));//ok 不同对象
        System.out.println("set="+set);
        //set=[Dog{name='tom'}, Dog{name='tom'}, lucy]

        //经典面试题
        set.add(new String("hsp"));//ok
        set.add(new String("hsp"));//加入不了 看源码
        System.out.println("set="+set);
        //set=[Dog{name='tom'}, hsp, Dog{name='tom'}, lucy]
    }
}
class Dog{
    private String name;

    public Dog(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                '}';
    }
}

 2、HashSet底层机制说明:(主要研究源码)

HashSet底层是HashMap,HashMap底层是(数组+链表+红黑树)

package Collection_;
@SuppressWarnings({"all"})
public class HashSetStructure {
    public static void main(String[] args) {
        //1、创建一个Node类型的数组
        Node[] table=new Node[16];
        System.out.println("table="+table);

        //2、创建结点
        Node john=new Node("jonh",null);
        table[2]=john;
        Node jack=new Node("jack",null);
        john.next=jack;//将jack结点挂载到john
        Node rose=new Node("Rose",null);
        jack.next=rose;//将rose结点挂载到jack
        System.out.println("table="+table);
    }
}
class Node{//结点,存储数据,可以指向下一个结点,从而形成链表
    Object item;//存放数据
    Node next;//指向下一个结点

    public Node(Object item, Node next) {
        this.item = item;
        this.next = next;
    }

    @Override
    public String toString() {
        return "Node{" +
                "item=" + item +
                ", next=" + next +
                '}';
    }
}

注意:equals的判断标准并不能简单地认为是两个字符串比较,因为String已经重写了equals方法,所以equals的判断标准和String没有关系,要视具体情况而定

//源码部分,非战斗人员,请做好撤退准备
package Collection_;

import javax.swing.tree.TreeNode;
import java.util.HashMap;
import java.util.HashSet;
@SuppressWarnings({"all"})
public class HashSetSource {
    public static void main(String[] args) {
        HashSet hashSet=new HashSet();
        hashSet.add("java");
        hashSet.add("php");
        hashSet.add("java");
        System.out.println("set="+hashSet);
        /*
        追源码:
        //1、执行HashSet()
        public HashSet() {
                map = new HashMap<>();
            }
        //2、执行add方法
        public boolean add(E e) {
                return map.put(e, PRESENT)==null;
                //PRESENT的源码: private static final Object PRESENT = new Object();主要起到占位的作用
            }
        //3、执行put方法,该方法会执行hash(key),得到key对应的hash值,
        //(hash(key)与hashcode不一样,hash(key)里面还包含了算法)相关算法: (h = key.hashCode()) ^ (h >>> 16)
        public V put(K key, V value) {//是PRESENT的值
                return putVal(hash(key), key, value, false, true);
            }
        //4、执行 putVal(核心代码)
         final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                           boolean evict) {
                Node<K,V>[] tab; Node<K,V> p; int n, i;//定义了辅助变量
                //table是HashMap的一个数组,类型是Node[]
                //if语句表示如果当前table是null,或者大小=0
                //就是第一次扩容到16个空间
                if ((tab = table) == null || (n = tab.length) == 0)
                    n = (tab = resize()).length;
                //(1)根据key,得到hash去计算该key应该存放到table表的哪个索引位置
                //并把这个位置的对象,赋给p
                //(2)判断p是否为null
                //(2.1)如果p为null,表示还没有存放元素,就创建一个Node(key="java",value=PRESENT)
                //(2.2)否则,就放在该位置tab[i] = newNode(hash, key, value, null);
                if ((p = tab[i = (n - 1) & hash]) == null)
                    tab[i] = newNode(hash, key, value, null);
                else {
                //一个开发技巧提示:在需要局部变量(辅助变量)时,再创建
                    Node<K,V> e; K k;
                    //如果当前索引位置对应的链表的第一个元素和准备添加的key的hash值一样
                    //并且满足下面两个条件之一:
                    //(1)准备加入的key和p指向的Node的结点的key是同一个对象
                    //(2)p指向的Node结点的key的equals()和准备加入的key比较后相同
                    //就不能加入
                    if (p.hash == hash &&
                        ((k = p.key) == key || (key != null && key.equals(k))))
                        e = p;
                        //再判断p是不是一棵红黑树
                        //如果是一棵红黑树,就调用putTreeVal来进行添加
                    else if (p instanceof TreeNode)
                        e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
                    else {
                    //如果table对应索引位置,已经是一个链表,就使用for循环比较
                    //(1)依次和该链表的每一元素比较后,都不相同,就加入到该链表的最后
                    //    注意在把元素添加到链表后,立即判断该链表是否已经达到8个结点
                    //    就调用treeifyBin()对当前这个链表进行树化(转成红黑树)
                    //    注意,在转成红黑树时,要进行判断,判断条件
                    //    if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
                    //            resize();
                    //    如果上面条件成立,先table扩容
                    //    只有上面条件不成立时,才进行转成红黑树
                    //(2)依次和该链表的每一个元素比较过程中,如果有相同情况,就直接break
                        for (int binCount = 0; ; ++binCount) {
                            if ((e = p.next) == null) {
                                p.next = newNode(hash, key, value, null);
                                if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                                    treeifyBin(tab, hash);
                                break;
                            }
                            if (e.hash == hash &&
                                ((k = e.key) == key || (key != null && key.equals(k))))
                                break;
                            p = e;
                        }
                    }
                    if (e != null) { // existing mapping for key
                        V oldValue = e.value;
                        if (!onlyIfAbsent || oldValue == null)
                            e.value = value;
                        afterNodeAccess(e);
                        return oldValue;
                    }
                }
                ++modCount;
                //size就是我们每加入一个结点Node(k,v,h,next),size++
                if (++size > threshold)
                    resize();
                afterNodeInsertion(evict);
                return null;
            }
            */
    }
}

3、练习题:

(1)

//我的代码:

package Collection_;

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

@SuppressWarnings({"all"})
public class HashSetExercise {
    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        Employee[] employees = new Employee[4];
        employees[0]=new Employee("jack", 18);
        employees[1]=new Employee("tom", 19);
        employees[2]=new Employee("rose", 20);
        employees[3]=new Employee("rose", 20);
        hashSet.add(employees[0]);
        for (int i = 1; i < employees.length; i++) {
            int tmp=0;
            Iterator iterator=hashSet.iterator();
            while (iterator.hasNext()) {
                Object next =  iterator.next();
                if (employees[i].getAge() == hashSet.hashCode()|| employees[i].getName().equals(hashSet.hashCode())) {
                    break;
                }
            }
            hashSet.add(employees[i]);
        }
        for (Object o :hashSet) {
            System.out.println(o);
        }
    }
}
class Employee{
    private String name;
    private int age;

    public Employee(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;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

 //老师的代码:

package Collection_;

import java.util.HashSet;
import java.util.Objects;
@SuppressWarnings({"all"})
public class HashSetExercise {
    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        hashSet.add(new Employee("milan",18));
        hashSet.add(new Employee("jack",28));
        hashSet.add(new Employee("milan",18));
        System.out.println("hashSet="+hashSet);
    }
}
class Employee{
    private String name;
    private int age;

    public Employee(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;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    //重写equals()方法和hashCode()方法:
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return age == employee.age && Objects.equals(name, employee.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
//hashSet=[Employee{name='milan', age=18}, Employee{name='jack', age=28}]

·重写equals()方法和hashCode()方法:

alt+insert---->---->下一步---->---->下一步---->

 (2)

 //我的代码

package Collection_;

import java.util.HashSet;
import java.util.Objects;

@SuppressWarnings({"all"})
public class HashSetExercise02 {
    public static void main(String[] args) {
        HashSet hashSet=new HashSet();
        MyDate jack=new MyDate(2000,1,1);
        MyDate tom=new MyDate(2001,2,2);
        hashSet.add(new Employee("jack",20000,jack));
        hashSet.add(new Employee("tom",30000,tom));
        hashSet.add(new Employee("jack",20000,jack));
        System.out.println(hashSet);
    }
}
class Employee{
    private String name;
    private double sal;
    private MyDate birthday;

    public Employee(String name, double sal, MyDate birthday) {
        this.name = name;
        this.sal = sal;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSal() {
        return sal;
    }

    public void setSal(double sal) {
        this.sal = sal;
    }

    public MyDate getBirthday() {
        return birthday;
    }

    public void setBirthday(MyDate birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", sal=" + sal +
                ", birthday=" + birthday +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return Objects.equals(name, employee.name) && Objects.equals(birthday, employee.birthday);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, birthday);
    }
}
class MyDate{
    private int year;
    private int month;
    private int day;

    public MyDate(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public int getDay() {
        return day;
    }

    public void setDay(int day) {
        this.day = day;
    }

    @Override
    public String toString() {
        return "MyDate{" +
                "year=" + year +
                ", month=" + month +
                ", day=" + day +
                '}';
    }
}
//[Employee{name='jack', sal=20000.0, birthday=MyDate{year=2000, month=1, day=1}}, Employee{name='tom', sal=30000.0, birthday=MyDate{year=2001, month=2, day=2}}]

 三、LinkedHashSet

1、基本介绍:

(1)LinkedHashSet 是 HashSet的子类

(2)LinkedHashSet 底层是一个 LinkedHashMap,底层维护了一个数组+双向链表

(3)LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,同时使 用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。

 

(4)LinkedHashSet 不允许添重复元素

2、LinkedHashSet底层机制:

package Collection_;

import java.util.LinkedHashSet;
import java.util.Set;
@SuppressWarnings({"all"})
public class LinkedHashSetSource {
    public static void main(String[] args) {
        Set set=new LinkedHashSet();
        set.add(new String("AA"));
        set.add(456);
        set.add(456);
        set.add(new Customer("刘",1001));
        set.add(123);
        set.add("HSP");
    }
}
class Customer{
    private String name;
    private int no;

    public Customer(String name, int no) {
        this.name = name;
        this.no = no;
    }
}

 3、练习题:

 //我的代码:

package Collection_;

import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
@SuppressWarnings({"all"})
public class LinkedHashSet_ {
    public static void main(String[] args) {
        Set linkedHashSet=new LinkedHashSet();
        linkedHashSet.add(new Car("奥拓",1000));
        linkedHashSet.add(new Car("奥迪",300000));
        linkedHashSet.add(new Car("法拉利",10000000));
        linkedHashSet.add(new Car("保时捷",70000000));
        linkedHashSet.add(new Car("奥迪",300000));
        System.out.println("linkedHashSet="+linkedHashSet);
    }
    public static class Car {
        private String name;
        private double price;

        public Car(String name, double price) {
            this.name = name;
            this.price = price;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public double getPrice() {
            return price;
        }

        public void setPrice(double price) {
            this.price = price;
        }

        @Override
        public String toString() {
            return "Car{" +
                    "name='" + name + '\'' +
                    ", price=" + price +
                    '}';
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Car car = (Car) o;
            return Double.compare(car.price, price) == 0 && Objects.equals(name, car.name);
        }

        @Override
        public int hashCode() {
            return Objects.hash(name, price);
        }
    }
}
//linkedHashSet=[Car{name='奥拓', price=1000.0}, Car{name='奥迪', price=300000.0}, Car{name='法拉利', price=1.0E7}, Car{name='保时捷', price=7.0E7}]

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

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

相关文章

闪电连接算法之Python实现

文章目录简介原理Python实现简介 LAPO&#xff0c;即闪电连接优化(Lightning Attachment Procedure Optimization)&#xff0c;听名字就知道是受到了闪电的刺激&#xff0c;而获得灵感的一种算法。 为了走进LAPO的内心&#xff0c;于是上网搜了一下闪电的图片 呃不好意思&…

网页设计期末作业,基于HTML+CSS+JavaScript超酷超炫的汽车类企业网站(6页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

商用短链平台_第8章_ 账号微服务注册模块+短信验证码+阿里云OSS开发实战

商用短链平台_第8章_ 账号微服务注册模块短信验证码阿里云OSS开发实战 文章目录商用短链平台_第8章_ 账号微服务注册模块短信验证码阿里云OSS开发实战第八章 账号微服务注册模块短信验证码阿里云OSS开发实战第1集 账号微服务注册功能和流程介绍第2集 第三方短信验证码平台接入申…

1802907-97-6|Alkyne PEG5 甲基四嗪|炔基点击试剂

【中文名称】甲基四嗪-五聚乙二醇-炔&#xff0c;甲氨基-五聚乙二醇-炔基 【英文名称】 Methyltetrazine-PEG5-alkyne&#xff0c;Alkyne PEG5 Methyltetrazine 【结 构 式】 【CAS号】1802907-97-6 【分子式】C20H26N4O5 【分子量】402.45 【基团】炔基基团 【纯度】95% 【规…

数据分析案例-大数据相关招聘岗位可视化分析

数据集介绍 本次数据集来源于xx招聘网共计4223条招聘信息&#xff0c;每条招聘信息字段包括岗位名称、公司名称、工作经验要求、学历要求、工作地点、薪酬、公司规模、发布时间、公司福利共9条字段信息。 数据预处理 首先导入本次数据集&#xff0c; import pandas as pd da…

使用Cent Browser+Aria2+Bilibili Envolved下载b站视频--保姆级安装步骤

1 使用前准备 Cent Browser百分浏览器下载&#xff1a;https://www.centbrowser.cn/加强版谷歌浏览器&#xff0c;chrome内核。 Tempermonkey&#xff1a;https://chrome.zzzmh.cn/info/dhdgffkkebhmkfjojejmpbldmpobfkfo Aria2&#xff1a;https://github.com/aria2/aria2/re…

外汇天眼:多位支持加息放缓!美元走弱黄金上涨

黄金小时图 黄金方面&#xff1a; 周三&#xff08;11月23日&#xff09;晚间&#xff0c;黄金短线下挫至1728美元之后快速收回。 美联储11月的会议纪要显示&#xff0c;尽管通胀前景风险上行&#xff0c;但大多数的与会者认为尽早放缓加息是合适的&#xff0c;利率正在接近足…

哪些岗位需要考CDMP/CDGA/CDGP证书?

大数据时代&#xff0c;数据成为社会和组织的宝贵资产&#xff0c;像工业时代的石油和电力一样驱动万物。假如数据的真实性、可用性大打折扣&#xff0c;那么数据的价值将会大大折扣&#xff0c;甚至根本不可用&#xff0c;不敢用。因此&#xff0c;数据治理是大数据时代我们用…

把报文再扔回内核,DPDK这样做

在DPDK中经常看到一个词&#xff0c;exception path&#xff0c;它是什么&#xff1f; 在DPDK使用环境中&#xff0c;物理网卡收到的报文不再进入内核协议栈&#xff0c;而是直接到达DPDK应用。但是在有些场景中&#xff0c;用户希望把报文&#xff08;如控制报文&#xff09;…

iTOP3A5000_7A2000开发板龙芯全国产处理器LoongArch架构核心主板

主要参数 处理器: 龙芯3A5000 主频: 2.3GHz-2.5GHz 桥片: 7A2000 内存: 8GB、16GB DDR4带ECC纠错&#xff08;配置可选&#xff09; 系统: Loongnix 典型功耗: 35W 核心板: 16层 底板: 4层 核心板参数 尺寸: 125*95mm CPU: 龙芯四核3A5000处理器 主频: 2.3GHz-2.5GHz 桥片…

101个CV模型集体开源,魔搭社区视觉AI深度解析

作者&#xff1a;谢宣松 达摩院开放视觉智能团队 11月3日&#xff0c;在2022云栖大会上&#xff0c;阿里达摩院联手 CCF 开源发展委员会共同推出了 AI 模型社区“魔搭”ModelScope&#xff0c;旨在降低 AI 的应用门槛。 AI 模型较为复杂&#xff0c;尤其是要应用于行业场景&…

前后端分离项目,vue+uni-app+php+mysql在线考试系统设计与实现(H5移动项目)

功能介绍 用户首次登陆系统需要注册一个用户或直接使用微信作为账号&#xff0c;用户在登录平台后&#xff0c;可以进行平台的操作。主要模块包括以下几点&#xff1a; 注册登录功能&#xff1a;注册普通账号登录&#xff1b;也可以直接使用微信登录&#xff1b;登录后可以修改…

python学习——numpy库的使用[超详细的学习笔记]

目录 前言 1 导入及查看版本信息 2 数组的创建 2.1 基础数据类型转换为数组 2.2 数组内置方法 2.2.1 np.arange() 线性序列数组 2.2.2 np.linspace() 等差数组 2.2.3 np.logspace() 等比数组 2.2.4 np.zeros() 全零的数组 2.2.5 np.ons() 全一的数组 float型 2.2.6 np.zeros_…

浅谈数商云供应链协同系统物流管理功能在医疗器械行业的作用

近年来&#xff0c;我国医疗器械行业发展快速&#xff0c;但医疗器械物流作为医疗器械供应链中承上启下的重要环节&#xff0c;目前仍处于相对传统和粗放的发展阶段。随着国家经济的发展及人民对医疗健康需求的不断增加&#xff0c;医疗器械供应链与物流的升级已是大势所趋。 …

程序员在平台兼职接单,月入30K,方法我全写出来了!(附接单渠道和注意事项)

本月兼职的收入又到账了&#xff0c;程序员副业实在是太香了&#xff01; 虽然这点小钱还远远达不到财富自由&#xff0c;也比不上那些真正的大佬&#xff0c;但在这个行业寒冬里&#xff0c;能有一笔相对稳定的收入&#xff0c;作为全职之外的补充&#xff0c;还是让人倍感踏实…

海棉结构sponge construction

海棉结构&#xff0c;或称海绵哈希&#xff0c;是当前密码学中一种重要构造结构&#xff0c;如当前sha-3采用的即是海绵结构。 海绵结构是一类具有有限内部状态的算法&#xff0c;可以将任意有限长的输入消息变成任意长度输出的消息摘要&#xff0c;其结构如下&#xff0c;其中…

docker-network网络

docker network网桥 作用&#xff1a;实现主机和容器之间可以通过网桥相互通信。 定义 正常不指定网络的情况下。所有的应用都跑在一个网桥上,影响其他应用的交互、网络传输。一般都是一个应用使用一个网桥&#xff0c;容器之间互通&#xff0c;则进行容器间通信的配置&…

粉丝提问:26想转行做Python开发,是不是已经晚了?

前言 26岁基本上是一个硕士研究生刚毕业的年纪&#xff0c;相当于本科毕业工作了2年&#xff0c;总体来说时间耽误的并不算太多&#xff0c;想转行做Python开发&#xff0c;不算太晚&#xff01; &#xff08;文末送读者福利&#xff09; 1、转行前先想清楚这5点&#xff01…

【vue.js】使用高德地图选择省市区后,再点击确认当前选择的位置

成品展示 前期准备 先去高德开放平台申请一个web端的key。 2022年后申请的key&#xff0c;必须和它生成的secret一起使用。 可使用服务选择web端 在vue项目中&#xff0c;可以通过直接引入js文件&#xff0c;也可以安装vue-amap等插件使用。 使用 安装官方的js API 插件 …

数据治理系列:数仓建模之数仓主题与主题域

背景&#xff1a; 数据仓库之父 Bill Inmon 将数据仓库描述为一个面向主题的、集成的、稳定的、反应历史变化的数据集合&#xff0c;用于支持管理者的决策过程。 从上面的引言里面&#xff0c;我们其实可以知道主题在数仓建设里面绝对是很重要的一环&#xff0c;这的确是的。…