JAVA9新特性

news2024/11/19 15:27:47

JAVA9新特性

概述

​ 经过4次推迟,历经曲折的Java9最终在2017年9月21日发布。因为里面加入的模块化系统,在最初设想的时候并没有想过那么复杂,花费的时间超出预估时间。距离java8大约三年时间。
​ Java 9提供了超过150项新功能特性,包括备受期待的模块化系统、可交互的REPL工具: jshell, JDK编译工具,语法层面的改变:Java公共API和私有代码,以及安全增强、扩展提升、性能管理改善等。可以说Java 9是一个庞大的系统工程,完全做了一个整体改变。
​ 但是这个巨大改变的功劳,都给了java11了,目前oracle对8,11都长期支持,9,10不支持了,只能从历史版本(http://jdk.java.net/)中下载,Java 11 将会获得 Oracle 提供的长期支持服务,直至2026年9月。
​ 从Java9这个版本开始,Java 的计划发布周期是6个月,下一个Java的主版本将于2018年3月发布,命名为Java18.3(java10), 紧接着再过六个月将发布Java18.9(java11).
​ 这意味着Java的更新从传统的以特性驱动的发布周期,转变为以时间驱动的(6个月为周期)发布模式(更快的时间周期,oracle的理念就是小步快跑,快速迭代,像IBM(DB2数据库,保守型内部测试才投入市场)),并逐步的将Oracle JDK原商业特性进行开源。针对企业客户的需求,Oracle将以三年为周期发布长期支持版本(long term support)

  • 重大改变:
    1 模块化系统
    2 jShell命令
  • 语法层面改变:
    1 接口私有方法
    2 钻石操作符(泛型<>)使用升级
    3 语法改进:try语句
  • API层面变化:
    1 String存储结构变更 (从char类型数组变为byte类型数组)
    2 集合特性:of()
    3 增强的Stream API(不断迭代,要重视这个Stream)
    4 全新的HTTP客户端API(不仅支持HTTP1.1而且还支持HTTP2:从5 以前的HttpUrlConnection-变为现在的HttpClient)
    6 Deprecated的 API
  • 其它变化:
    1 javadoc的HTML5支持
    2 Js引擎升级:Nashorn(9对8升级了,但是11里又没有了)
    3 java的动态编译器
    4 多版本兼容jar包

官方提供的新特性的列表

https://docs.oracle.com/javase/9/whatsnew/toc.htm#JSNEW-GUID-C23AFD78-C777-460B-8ACE-58BE5EA681F6

openJDK 可参考源码

http://openjdk.java.net/projects/jdk9/

在线 OracleJDK Documentation 在线文档

https://docs.oracle.com/javase/9/

JDK和JRE的目录的改变

1629877485595

bin 包含命令行开发和调试工具 如javac jar javadoc

include 包含编译本地代码时使用的c/c++头部文件

lib 包含JDK工具的几个jar和其他类型的文件,他有一个tools.jar文件,其中含javac编译器的java类

jre/bin目录 包含基本指令,如java指令,在windows平台上,它包含系统的运行时动态链接

jre/lib包含用户可编辑的配置文件,如properties和.policy文件,包含几个jar文件,rt.jar文件包含运行时的java类和资源文件

1629877501349

bin 包含所有指令,在windows平台上,他继续包含系统的运行时动态链接

conf目录 包含用户可编辑的配置文件,例如之前位于jre/lib目录中的.properties和policy

includes 包含在以前编译本地代码时使用c/c++头文件,他只存在于JDK中

jmods 包含JMOD格式的平台模块,创建自定义运行时映像需要他,它只存在于jdk中

legal 法律声明

lib 包含非windows平台上的动态链接本地库,其子目录和文件不应由开发人员直接编译或使用

从9开始以后的JDK目录结构都是如此

一 语法层次的改变

1_钻石操作符号语法升级

钻石操作符,就是我们泛型使用的符号<>

JAVA8 中,匿名内部类不能使用钻石操作符,如下代码在JAVA8 中是报错的,匿名内部类这里不支持泛型推断,重写的方法不明确泛型

1629966490626

这里匿名内部类中的<>号里必须要和前面的声明保持一致,不能空着不写,这样重写的方法就根据匿名内部类的泛型

1629966550374

但是这种写法在JAVA9 中就允许了

1629966634077

而且在JAVA9中,匿名内部类的语法不仅仅可以用于接口和抽象类,普通类也可以通过匿名内部类写法,在某个实例上完成对某个方法的重写

public class Demo1 {
    public static void main(String[] args) {
        /*
        * 匿名内部类仅仅在接口和抽象类上使用,作为一种快速的实现方式
        * JAVA9中,普通类也可以借助这种语法形式实现对方法的快速临时的重写
        * */
        Person<String> person=new Person<>(){
            @Override
            public void eat(String s) {
                super.eat(s);
            }
        };
        person.eat("包子");

    }
}
class Person<T>{
    public void eat(T t){
        System.out.println("Person eat");
    }
}

2_try结构语法升级

普通的try catch finally语句 要释放的资源可以放到finally语句块中

        InputStreamReader reader =null;
        try{
            reader =new InputStreamReader(System.in);
            int read = reader.read();
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            // 这里可以释放资源
            if(null != reader){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

JAVA 8中已经对try语法进行了升级,可以将要释放的资源放到try后面的小括号中,这样就不用通过finally语句块释放资源了,但是要求执行后必须关闭的资源一定要放在try子句中进行初始化,否则编译不通过. 下面的案例中,reader必须放在try后面的小括号中进行初始化

        try( InputStreamReader reader=new InputStreamReader(System.in) ){
            int read = reader.read();
        }catch (Exception e){
            throw new RuntimeException(e);
        }

JAVA 9 资源的关闭操作,我们可以在try子句中使用已经初始化的资源但是此时的资源必须 是final修饰的,final可以省略不写

/**
 * @Author: Ma HaiYang
 * @Description: MircoMessage:Mark_7001
 */
public class Demo2 {
    public void testx(){
        // 传统的 try catch finally语句块
        InputStreamReader isr =null;
        try{
            isr =new InputStreamReader(new FileInputStream("d:/aaa.txt"));
            isr.read();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(null != isr){
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    // JAVA8 try语法升级
    public void testa(){
        // JAVA8 try catch finally语句块
        try( InputStreamReader isr =new InputStreamReader(new FileInputStream("d:/aaa.txt"));){
            isr.read();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    // JAVA9 try语法升级
    public void testb() throws FileNotFoundException {
        // JAVA9 try catch finally语句块
        InputStreamReader isr =new InputStreamReader(new FileInputStream("d:/aaa.txt"));
        OutputStreamWriter isw =new OutputStreamWriter(new FileOutputStream("d:/aaa.txt"));
        try( isr; isw){
            isr.read();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

3_下划线命名标识符的使用限制

标识符命名组成:字母,数字,下划线,美元符

JAVA8 中,可以使用一个 _ 作为标识符的命名

String  _  ="宇智波赵四儿";

JAVA9 中,就不可以使用一个_ 作为标识符的命名了,不通过编译,但是标识符中仍然可以使用_,必须配合其他内容

String stu_name="旋涡刘能";

小细节,注意一下即可,一般也没人直接单独用一个_ 作为标识符的命名

二 API层次的改变

1_接口中的私有方法

JAVA7 中,接口只能有抽象方法

JAVA8 中,接口中static(静态不可重写)和default(可以重写)修饰的方法可以拥有方法体

JAVA9 中,接口中可以使用private修饰方法,并拥有方法体,但是接口中的成员变量仍然不能用private修饰

感觉: 接口中的代码越来越靠近抽象类,但是仍然是支持多继承的

1629968793799

/**
 * @Author: Ma HaiYang
 * @Description: MircoMessage:Mark_7001
 */
public class Demo4 {
    // 接口,是一种规范和要求
    // 实现多继承
}
// java7 接口中的方法必须都是抽象的
interface  Inter1{
    void methoda();
}
// java8接口可以定义static/default修饰的非抽象方法
interface  Inter2{
    void methoda();
    static void methodB(){

    }
    default void methodC(){

    }
}
// java9 允许定义私有的非抽象方法
interface  Inter3{
    void methoda();
    static void methodB(){

    }
    default void methodC(){
        methodD();
    }
    private void methodD(){

    }
}

2_String底层存储结构的变更

JAVA8 中的String源码

String类内部维护的是一个final修饰的私有char数组,说明String的底层是通过char数组存储字符串的

1630032137816

JAVA9 中String的源码

String类内部维护的是一个final修饰的私有byte数组,说明String的底层是通过byte数组存储字符串的

1630032189562

这么做的原因:大多数String对象只包含latin-1字符。 这样的字符只需要一个字节的存储空间,因此这样的String对象的内部字符数组中有一半的空间没有使用 , 我们建议将String类的内部表示形式从UTF-16字符数组更改为一个字节数组加上一个结束编码标志字段

3_Stream新增4个API

JAVA9 中,Stream接口添加了4个新方法,takeWhile,dropWhile,ofNullable,还有一个iterate 方法的新重载方法,可以通过一个Predicate来指定什么时候结束迭代

 /**
     * 测试Stream新增takeWhile方法
     * takeWhile  从流中的头开始取元素,直到不满足条件为止
     */
    public static void testTakeWhile(){
        List<Integer> list = Arrays.asList(1, 89, 63, 45, 72, 65, 41, 65, 82, 35, 95, 100);
        // 从头开始取所有奇数,直到遇见一个偶数为止
        list = list.stream().takeWhile(e -> e % 2 == 1).collect(Collectors.toList());
        //[1, 89, 63, 45]
        System.out.println(list);
    }

    /**
     * 测试Stream新增dropWhile方法
     * dropWhile  从头开始删除满足条件的数据,直到遇见第一个不满足的位置,并保留剩余元素
     */
    public static void testDropWhile() {
        List<Integer> list = Arrays.asList(2, 86, 63, 45, 72, 65, 41, 65, 82, 35, 95, 100);
        // 删除流开头所有的偶数,直到遇见奇数为止
        list = list.stream().dropWhile(e -> e % 2 == 0).collect(Collectors.toList());
        //[63, 45, 72, 65, 41, 65, 82, 35, 95, 100]
        System.out.println(list);
    }

    /**
     * 测试Stream新增ofNullable方法
     * ofNullable 允许创建Stream流时,只放入一个null
     */
    public static void testOfNullable(){
        // of方法获取流 ,允许元素中有多个null值
        Stream<Integer> stream1 = Stream.of(10, 20, 30, null);
        // 如果元素中只有一个null,是不允许的
        Stream<Integer> stream2 = Stream.of(null);
        // JAVA9中,如果元素为null,返回的是一个空Stream,如果不为null,返回一个只有一个元素的Stream
        Stream<Integer> stream3 = Stream.ofNullable(null);
    }

    /**
     * 测试Stream新增iterate方法
     * iterate指定种子数,指定条件和迭代方式来获取流
     */
    public static void testNewIterate(){
        //JAVA8通过 generate方法获取一个Stream
        Stream.generate(Math::random).limit(10).forEach(System.out::println);
        //JAVA8 通过iterate获取一个Stream
        Stream.iterate(0,t-> t+2).limit(10).forEach(System.out::println);
        //JAVA9通过重载iterate获取Stream
        Stream.iterate(0,t -> t<10,t-> t+1).forEach(System.out::println);
    }

除了Stream本身的扩展,Optional和Stream之间的结合也得到了改进,现在可以通过Optional的新方法将一个Optional对象转换为一个Stream对象(可能是空的)

    /**
     * Optional类新增Stream方法,可以将一个Optional转换为Stream
     */
    public static void testOptionalStream(){
        List<Integer> list =new ArrayList<>();
        Collections.addAll(list,10,5,45,95,36,85,47);
        Optional<List<Integer>> optional=Optional.ofNullable(list);

        // 通过optional的Stream方法获取一个Stream
        Stream<List<Integer>> stream = optional.stream();
        // 以为内部的每个元素也是一个List,通过flatMap方法,将内部的List转换为Stream后再放入一个大Stream
        stream.flatMap(x->x.stream()).forEach(System.out::println);

    }

4_InputStream新增transferTo方法

InputStream新增transferTo方法,可以用来将数据直接传输到OutpuStream,这是在处理原始数据时非常常见的一种方法

        InputStream inputStream =new FileInputStream("d:/aaa.txt");
        OutputStream outputStream=new FileOutputStream("d:/bbb.txt");
        try (inputStream;outputStream){
            //将aaa.txt文件写入到bbb.txt
            inputStream.transferTo(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

5_只读集合的创建

JAVA8 要创建一个只读,不可改变的集合,必须构造和分配他,然后添加元素,然后再包装成一个不可修的集合

        List<String> list= new ArrayList<>();
        list.add("Tom");
        list.add("Jerry");
        list.add("Mark");
        list.add("Jhon");
        list = Collections.unmodifiableList(list);
        System.out.println(list);

放入数据后,然后要通过unmodifiableList才能让集合变为只读集合,不能表达为单个的表达式

JAVA9 通过集合工厂方法,创建一个只读集合,只要通过新增的of方法即可完成创建

        List<String> list= List.of("TOM","Jerry","Mark","Ben");
		//[TOM, Jerry, Mark, Ben]
        System.out.println(list);

1630035230203

上面是List接口的of方法, 同样的,Set接口和Map接口下也新增了of方法,也是返回一个只读集合

三 其他变化

1_JAVA9 模块化

谈到Java9大家往往第一个想到的就是Jigsaw项目(后改名为Modularity)。众所周知,Java已经发展超过20年(95年最初发布),Java和相关生态在不断丰富的同时也越来越暴露出一些问题:

1Java运行环境的膨胀和臃肿。每次JVM启动的时候,至少会有30~ 60MB的内存加载,主要原因是JVM需要加载rt.jar,不管其中的类是否被classloader加载,第一步整个jar都会被JVM加载到内存当中去(而模块化可以根据模块的需要加载程序运行需要的class)

2当代码库越来越大,创建复杂,盘根错节的“意大利面条式代码”的几率呈指数级的增长。不同版本的类库交叉依赖导致让人头疼的问题,这些都阻碍了Java 开发和运行效率的提升。

3很难真正地对代码进行封装,而系统并没有对不同部分(也就是JAR文件)之间的依赖关系有个明确的概念。每一个公共类都可以被类路径之下任何其它的公共类所访问到,这样就会导致无意中使用了并不想被公开访问的API.

本质上讲,模块化,就是在package外面包裹一层->>>说白了项目下有众多 模块
进行项目管理,管理各个模块,比如一个电商项目 下面有支付模块 购物模块,,,模块跟模块之间相互调用,这样代码就更安全,可以指定哪些暴露 哪些隐藏!

模块之间的可访问性是所使用的模块和使用模块之间的双向协议:模块明确地使其公共类型可供其他模块使用,而且使用这些公共类型的模块明确声明对第一个模块的依赖,模块中所有未导出的软件包都是模块的私有的,他们不能在模块之外使用.之前做不到,现在可以考虑这个事了

在jdk9中,项目模块之间的依赖

在JDK9 先准备一个项目,普通java项目即可,然后再项目下准备两个模块,名字为jdk9module1和jdk9module2,如下图

1629959034495

jdk9module1中添加一些类

如何在jdk9module2中使用这个类? 或者说是使用模块1中的类,第一步,在两个模块的src下创建各自的module-info.java

image-20230506160018321

在jdk9module1的module-info.java文件中,设置哪些包可以向外暴露

module jdk9module1 {
    //设置当前模块可以对外保留的包
    exports com.llp.pojo;
}

在jdk9module2的module-info.java中引入模块1

module jdk9module2 {
    requires jdk9module1;
}

但是发现报错了,原因是,我们要把模块1添加为模块2的运行环境,具体操作如下

project structure > modules > jdk9module2 >dependencies >>+module lib > jdk9module1 > apply >>ok

image-20230506160356723

这个是时候,我们在模块2中就可以使用模块1 中的类了

image-20230506160441195

2_可交互的REPL工具:jshell

像Python和Scala 之类的语言早就有交互式编程环境REPL (read -evaluate - print -loop)了,以交互式的方式对语句和表达式进行求值。开发者只需要输入一些代码,就可以在编译前获得对程序的反馈。而之前的Java 版本要想执行代码,必须创建文件、声明类、提供测试方法方可实现。

要想实现REPL,需要一个命令:JShell命令(linux中是shell命令,java中的shell命令)

1629877864498

将环境变量配置为java9,就可以在控制命令台使用jshell命令了:如果电脑上安装了其他版本的JDK,环境变量也是其他版本,大家可以在dos上通过cd 切换到指定版本的bin目录下,就可以使用该版本的jshell了

1629962311415

案例:简单输出语句:

1629877895300

案例:变量定义

1629877926195

案例:方法定义和调用:

1629877952559

1629877968367

导包:

1629877991221

其实jshell中有默认的导入一些包(除了java.lang之外,以下包也可以直接用),可以直接使用不用导包,查看有哪些:

1629878023330

常用命令:

1629878047871

1629878065195

可以将某些常用命令持久化在硬盘上:

1629878182887

1629878211555

jshell不用编译时异常处理:

1629878234271

退出jshell

1629878258920

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

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

相关文章

RSA加密的原理

一、RSA加密算法的原理 先上公式&#xff1a; 加密过程&#xff1a;其实就是明文的E次方对N取模公钥&#xff1a;&#xff08;E,N&#xff09;解密过程&#xff1a;密文的D次方对N取模私钥&#xff1a;&#xff08;D,N&#xff09;那么以上公式中的E、D、N分别代表什么&#x…

solidworks版本推荐

有不少人在入坑SolidWorks的时候&#xff0c;不知道下载哪一个版本&#xff0c;不清楚SolidWorks哪个版本更好用一些&#xff0c;其实选择适合自己的版本才是关键。那么该如何选择版本呢&#xff1f;不知道如何选择SOLIDWORKS版本的&#xff0c;可以参考以下3个方面。 一、SOL…

自动化测试工具的基本原理以及应用场景

自动化测试工具是现代软件开发流程中必不可少的组成部分&#xff0c;它可以通过编写脚本或使用图形用户界面工具自动化测试过程&#xff0c;提高测试的效率和准确性。本文将介绍自动化测试工具的基本原理以及应用场景。 自动化测试工具的基本原理 自动化测试工具通常采用的原理…

我与smardaten | 百天无码路,苦逼中带点小美好

大家好&#xff0c;我是云华&#xff08;化名&#xff09;&#xff0c;一个不太懂技术的无代码开发者&#xff0c;游走在无码世界的自由闲散人。现今是我从事无码开发的第四个月&#xff0c;已经从小白蜕变成了熟手。前两天&#xff0c;睿睿老师找到我&#xff0c;说最近计划办…

【wpf】枚举的绑定最易用法 和 全局静态绑定的应用

背景 有时我们做配置界面的时候&#xff0c;有很多配置项是枚举。通过我们会用一个Combobox实现&#xff0c;如果能直接用Combobox绑定枚举&#xff0c;那将会非常方便。这里绑定将涉及到两个方面&#xff0c;一个是数据源的绑定&#xff0c;还有就是当前选择项的绑定。最后我们…

每天一道算法练习题--Day23 第一章 --算法专题 --- ----------并查集

背景 相信大家都玩过下面的迷宫游戏。你的目标是从地图的某一个角落移动到地图的出口。规则很简单&#xff0c;仅仅你不能穿过墙。 实际上&#xff0c;这道题并不能够使用并查集来解决。 不过如果我将规则变成&#xff0c;“是否存在一条从入口到出口的路径”&#xff0c;那么…

DDR5内存彻底白菜价,国外大厂却整出了比着火更离谱的骚操作

今年的 PC 硬件市场&#xff0c;似乎出现了明显两极分化现象。 一边是 N、A 两家新显卡价格高高在上&#xff0c;摆明了不坑穷人。 另一边固态硬盘、内存条又在疯狂互卷不断杀价。 四五百元的 2TB SSD&#xff0c;二百元的 16G 内存条早已见怪不怪。 要说面世多年的 PCIe 3.0…

对比 LVS 负载均衡群集的 NAT 模式和 DR 模式,基于 CentOS 7 构建 LVS-DR 群集

1. 对比 LVS 负载均衡群集的 NAT 模式和 DR 模式&#xff0c;比较其各自的优势 。 LVS&#xff08;Linux Virtual Server&#xff09;是一个开源的负载均衡软件&#xff0c;它支持多种负载均衡算法&#xff0c;包括 NAT 模式和 DR &#xff08;Direct Routing&#xff09;模式…

【数据分析之道-Matplotlib(二)】Matplotlib 绘图标记

文章目录 专栏导读1、前言2、标记&#xff08;Markers&#xff09;2.1关键词参数marker2.2标记参考&#xff08;Marker Reference&#xff09; 3、Format Strings fmt3.1fmt参数3.2线参考&#xff08;Line Reference&#xff09; 4、标记颜色(Marker Color)4.1关键字参数mec4.2…

《程序员面试金典(第6版)》面试题 16.14. 最佳直线(向量,C++)

题目描述 给定一个二维平面及平面上的 N 个点列表Points&#xff0c;其中第i个点的坐标为Points[i][Xi,Yi]。请找出一条直线&#xff0c;其通过的点的数目最多。 设穿过最多点的直线所穿过的全部点编号从小到大排序的列表为S&#xff0c;你仅需返回[S[0],S[1]]作为答案&#xf…

简述对象检测与图像分类与关键点检测区别

计算机视觉是人工智能的一个多元化领域&#xff0c;旨在检测和识别图像或视频的内容。大多数开始计算机视觉领域之旅的人的常见问题之一是&#xff1a;目标检测、图像分类和关键点检测之间有什么区别&#xff1f; 让我们先看看 什么是对象检测 对象检测是一种计算机视觉和图像…

gateway sentinel 流控规则持久化到 nacos

Sentinel改造 sentinel版本是1.8.6 直接看更新内容, 右侧更新后 GatewayApiController /*** Gateway api Controller for manage gateway api definitions.** author cdfive* since 1.7.0*/ RestController RequestMapping(value "/gateway/api") public class…

【操作系统】内存空间

最小的操作系统Hello world 想要pmap这个进程&#xff0c;需要进程号 但是这个进程在启动的一瞬间就执行完了 用GDB把程序暂停下来&#xff0c;然后用pmap观察地址空间 用info inferiors得到gdb里的进程号 ro 可读 &#xff1a;只读数据 rx 可读可执行 &#xff1a;代码 rw 可…

Java学习:Scanner类及其应用

Java Scanner 一、next()二、nextLine()三、应用 一、next() 用于从标准输入读取下一个字符串。该方法会扫描输入流并返回下一个非空白字符序列&#xff0c;以空格、制表符或换行符作为分隔符 1、next()会以空格作为分隔符,一行输入1 2 3,只会打印出1 import java.util.Scan…

Java RSA密钥转换,从RSAPrivateKey得到RSAPublicKey

概述&#xff1a; 在Java编程中&#xff0c;我们经常用到如下一段代码来生成RSA公私钥&#xff0c;分别拿到公私钥然后加解密计算&#xff1a; KeyPairGenerator keyPairGen; keyPairGen KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(2048, new S…

Oracle Instant Client + PLSQL 部署终端PC远程连接数据库服务器简易操作

系统环境&#xff1a; 1、win7_64bit 2、instantclient_21_10 3、plsqldev1105_x64 4、远程Oracle数据库&#xff1a;Oracle11g R2 操作步骤&#xff1a; 1、下载好Oracle Instant Client 和PLSQL程序安装包&#xff1a; 1.1 Oracle Instant Client 官网&#xff1a;https://w…

MySQL基础(五)排序与分页

1. 排序数据 1.1 排序规则 使用 ORDER BY 子句排序 ASC&#xff08;ascend&#xff09;: 升序DESC&#xff08;descend&#xff09;:降序 ORDER BY 子句在SELECT语句的结尾。 1.2 单列排序 SELECT last_name, job_id, department_id, hire_date FROM employees ORDER…

Redis之三大特殊数据类型:Geospatial:地理位置 hyperloglog:实现的功能是计算统计 bitmaps:位存储

三大特殊数据类型结构&#xff0c;十分的少见但是开源项目中依然有它们的身影 Geospatial:地理位置 实现的功能&#xff1a;附近的人&#xff0c;城市与城市之前的距离计算 添加城市经纬度到key中&#xff0c;经纬度则是key的value值&#xff0c;在正常的开发过程中&#xf…

获得 随机验证码(以图片为底层)

1&#xff1a;工具类 Slf4j public class RandomValidateCode {private static String baseNumLetter "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";private static String font "微软雅黑";//绘制验证码图片,返回验证码文本内容pu…

【机器学习】pytorch安装——环境配置(极简教程)

&#x1f951; Welcome to Aedream同学 s blog! &#x1f951; 文章目录 省流总结新建环境确定显卡型号安装显卡驱动安装pytorch国内镜像下载本地下载 验证安装成功 最近重新配置环境&#xff0c;简单记录一下。最近chatgpt等大语言模型和ai绘图火热&#xff0c;也为了方便很多…