深入理解 Redis Template及4种序列化方式__spring boot整合redis实现RedisTemplate三分钟快速入门

概述

使用Spring 提供的 Spring Data Redis 操作redis 必然要使用Spring提供的模板类 RedisTemplate, 今天我们好好的看看这个模板类 。

RedisTemplate

在这里插入图片描述

看看4个序列化相关的属性 ,主要是 用于 KEY 和 VALUE 的序列化 。 举个例子,比如说我们经常会将POJO 对象存储到 Redis 中,一般情况下会使用 JSON 方式序列化成字符串,存储到 Redis 中 。

Spring提供的Redis数据结构的操作类

  • ValueOperations 类,提供 Redis String API 操作
  • ListOperations 类,提供 Redis List API 操作
  • SetOperations 类,提供 Redis Set API 操作
  • ZSetOperations 类,提供 Redis ZSet(Sorted Set) API 操作
  • GeoOperations 类,提供 Redis Geo API 操作
  • HyperLogLogOperations 类,提供 Redis HyperLogLog API 操作

StringRedisTemplate

再看个常用的 StringRedisTemplate

RedisTemplate<K, V> 支持泛型,StringRedisTemplate K V 均为String类型。

org.springframework.data.redis.core.StringRedisTemplate 继承 RedisTemplate 类,使用 org.springframework.data.redis.serializer.StringRedisSerializer 字符串序列化方式。

在这里插入图片描述

RedisSerializer 序列化 接口

RedisSerializer接口 是 Redis 序列化接口,用于 Redis KEY 和 VALUE 的序列化

在这里插入图片描述

RedisSerializer 接口的实现类 如下

在这里插入图片描述

归类一下

  • JDK 序列化方式 (默认)
  • String 序列化方式J
  • SON 序列化方式
  • XML 序列化方式

JDK 序列化方式 (默认)

org.springframework.data.redis.serializer.JdkSerializationRedisSerializer ,默认情况下,RedisTemplate 使用该数据列化方式。

我们来看下源码 RedisTemplate#afterPropertiesSet()

在这里插入图片描述

Spring Boot 自动化配置 RedisTemplate Bean 对象时,就未设置默认的序列化方式。

绝大多数情况下,不推荐使用 JdkSerializationRedisSerializer 进行序列化。主要是不方便人工排查数据。

我们来做个测试
在这里插入图片描述

运行单元测试

在这里插入图片描述

看不懂呀 ,老哥

KEY 前面带着奇怪的 16 进制字符 , VALUE 也是一串奇怪的 16 进制字符 。。。。。

为什么是这样一串奇怪的 16 进制? ObjectOutputStream#writeString(String str, boolean unshared) 实际就是标志位 + 字符串长度 + 字符串内容

KEY 被序列化成这样,线上通过 KEY 去查询对应的 VALUE非常不方便,所以 KEY 肯定是不能被这样序列化的。

VALUE 被序列化成这样,除了阅读可能困难一点,不支持跨语言外,实际上也没还OK。不过,实际线上场景,还是使用 JSON 序列化居多。

String 序列化方式

org.springframework.data.redis.serializer.StringRedisSerializer ,字符串和二进制数组的直接转换

在这里插入图片描述

绝大多数情况下,我们 KEY 和 VALUE 都会使用这种序列化方案。

JSON 序列化方式

org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer 使用 Jackson 实现 JSON 的序列化方式,并且从 Generic 单词可以看出,是支持所有类。

public GenericJackson2JsonRedisSerializer(@Nullable String classPropertyTypeName) {.......... if (StringUtils.hasText(classPropertyTypeName)) {mapper.enableDefaultTypingAsProperty(DefaultTyping.NON_FINAL, classPropertyTypeName);} else {mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);}}

classPropertyTypeName 不为空的话,使用传入对象的 classPropertyTypeName 属性对应的值,作为默认类型(Default Typing) ,否则使用传入对象的类全名,作为默认类型(Default Typing)。

我们来思考下,在将一个对象序列化成一个字符串,怎么保证字符串反序列化成对象的类型呢?Jackson 通过 Default Typing ,会在字符串多冗余一个类型,这样反序列化就知道具体的类型了

在这里插入图片描述

先说个结论

标准JSON

{"id": 100,"name": "小工匠","sex": "Male"
}

使用 Jackson Default Typing 机制序列化

{"@class": "com.artisan.domain.Artisan","id": 100,"name": "小工匠","sex": "Male"
}

示例

测试一把

【配置类】

 @Beanpublic RedisTemplate<String, Object> redisTemplate() {// 创建 RedisTemplate 对象RedisTemplate<String, Object> template = new RedisTemplate<>();// 设置 RedisConnection 工厂。 它就是实现多种 Java Redis 客户端接入的秘密工厂template.setConnectionFactory(connectionFactory);// 使用 String 序列化方式,序列化 KEY 。template.setKeySerializer(RedisSerializer.string());// 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。template.setValueSerializer(RedisSerializer.json());return template;}

【单元测试】

 @Beanpublic RedisTemplate<String, Object> redisTemplate() {// 创建 RedisTemplate 对象RedisTemplate<String, Object> template = new RedisTemplate<>();// 设置 RedisConnection 工厂。 它就是实现多种 Java Redis 客户端接入的秘密工厂template.setConnectionFactory(connectionFactory);// 使用 String 序列化方式,序列化 KEY 。template.setKeySerializer(RedisSerializer.string());// 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。template.setValueSerializer(RedisSerializer.json());return template;}

【结果】

在这里插入图片描述

是不是多了@class 属性,反序列化的对象的类型就可以从这里获取到。

@class 属性看似完美解决了反序列化后的对象类型,但是带来 JSON 字符串占用变大,所以实际项目中,我们很少采用 Jackson2JsonRedisSerializer

XML 序列化方式

org.springframework.data.redis.serializer.OxmSerializer使用 Spring OXM 实现将对象和 String 的转换,从而 String 和二进制数组的转换。 没见过哪个项目用过,不啰嗦了


spring boot整合redis实现RedisTemplate三分钟快速入门

引入依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

RedisTemplate五种数据结构的操作

  • redisTemplate.opsForValue(); //操作字符串
  • redisTemplate.opsForHash(); //操作hash
  • redisTemplate.opsForList(); //操作list
  • redisTemplate.opsForSet(); //操作set
  • redisTemplate.opsForZSet(); //操作有序zset

RedisTemplate方法讲解

判断key是否存在

 /*** 判断key是否存在*/@GetMapping("haskey")public boolean hasKey(String key) {return redisTemplate.hasKey(key);}

获取指定的key的失效时间

 /*** 指定key的失效时间*/@GetMapping("expire")public void expire(String key, long time) {//参数一:key//参数二:睡眠时间//参数三:睡眠时间单位 TimeUnit.DAYS 天 TimeUnit.HOURS 小时 。。。redisTemplate.expire(key, time, TimeUnit.MINUTES);}

根据key获取过期时间

 /*** 根据key获取过期时间*/@GetMapping("getexpire")public long getExpire(String key) {Long expire = redisTemplate.getExpire(key);return expire;}

根据key删除reids中缓存数据

 /*** 根据key删除reids中缓存数据*/@GetMapping("delredisbykey")public void delete(String key) {redisTemplate.delete(key);}

保存和读取String

 /*** 保存和读取String*/@GetMapping("stringredisdemo")public String stringredisdemo() {//设置过期时间为1分钟redisTemplate.opsForValue().set("key1", "value1", 1, TimeUnit.MINUTES);redisTemplate.opsForValue().set("key2", "value2");redisTemplate.opsForValue().set("key3", "value3");//读取redis数据String result1 = redisTemplate.opsForValue().get("key1").toString();String result2 = redisTemplate.opsForValue().get("key2").toString();String result3 = redisTemplate.opsForValue().get("key3").toString();System.out.println("缓存结果为:result:" + result1 + " " + result2 + "  " + result3);return "缓存结果为:result:" + result1 + " " + result2 + "  " + result3;}

保存和读取list

 /*** 保存和读取list*/@GetMapping("listredisdemo")public String listredisdemo() {List<String> list1 = new ArrayList<>();list1.add("a1");list1.add("a2");list1.add("a3");List<String> list2 = new ArrayList<>();list2.add("b1");list2.add("b2");list2.add("b3");redisTemplate.opsForList().leftPush("listkey1", list1);redisTemplate.opsForList().rightPush("listkey2", list2);List<String> resultList1 = (List<String>) redisTemplate.opsForList().leftPop("listkey1");List<String> resultList2 = (List<String>) redisTemplate.opsForList().rightPop("listkey2");System.out.println("resultList1:" + resultList1);System.out.println("resultList2:" + resultList2);return "成功";}

Hash结构,保存和读取map

 /*** Hash结构,保存和读取map*/@GetMapping("mapredisdemo")public String mapredisdemo() {Map<String, String> map = new HashMap<>();map.put("key1", "value1");map.put("key2", "value2");map.put("key3", "value3");map.put("key4", "value4");map.put("key5", "value5");redisTemplate.opsForHash().putAll("map1", map);Map<String, String> resultMap = redisTemplate.opsForHash().entries("map1");List<String> reslutMapList = redisTemplate.opsForHash().values("map1");Set<String> resultMapSet = redisTemplate.opsForHash().keys("map1");String value = (String) redisTemplate.opsForHash().get("map1", "key1");System.out.println("value:" + value);System.out.println("resultMapSet:" + resultMapSet);System.out.println("resultMap:" + resultMap);System.out.println("resulreslutMapListtMap:" + reslutMapList);return "成功";}

保存和读取Set

 /*** 保存和读取Set*/@GetMapping("setredisdemo")public String getredisdemo() {SetOperations<String, String> set = redisTemplate.opsForSet();set.add("key1", "value1");set.add("key1", "value2");set.add("key1", "value3");Set<String> resultSet = redisTemplate.opsForSet().members("key1");System.out.println("resultSet:" + resultSet);return "resultSet:" + resultSet;}

保存和读取zset

 /*** 保存和读取zset*/@GetMapping("zsetredisdemo")public String zsetredisdemo() {ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<>("zset-5", 9.6);ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<>("zset-6", 9.9);Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();tuples.add(objectTypedTuple1);tuples.add(objectTypedTuple2);System.out.println(redisTemplate.opsForZSet().add("zset1", tuples));System.out.println(redisTemplate.opsForZSet().range("zset1", 0, -1));return "成功";}

完整示例代码

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.*;
import java.util.concurrent.TimeUnit;@RestController
public class ReidsDemo {@AutowiredRedisTemplate redisTemplate;/*** 指定key的失效时间*/@GetMapping("expire")public void expire(String key, long time) {//参数一:key//参数二:睡眠时间//参数三:睡眠时间单位 TimeUnit.DAYS 天 TimeUnit.HOURS 小时 。。。redisTemplate.expire(key, time, TimeUnit.MINUTES);}/*** 根据key获取过期时间*/@GetMapping("getexpire")public long getExpire(String key) {Long expire = redisTemplate.getExpire(key);return expire;}/*** 判断key是否存在*/@GetMapping("haskey")public boolean hasKey(String key) {return redisTemplate.hasKey(key);}/*** 根据key删除reids中缓存数据*/@GetMapping("delredisbykey")public void delete(String key) {redisTemplate.delete(key);}/*** 保存和读取String*/@GetMapping("stringredisdemo")public String stringredisdemo() {//设置过期时间为1分钟redisTemplate.opsForValue().set("key1", "value1", 1, TimeUnit.MINUTES);redisTemplate.opsForValue().set("key2", "value2");redisTemplate.opsForValue().set("key3", "value3");//读取redis数据String result1 = redisTemplate.opsForValue().get("key1").toString();String result2 = redisTemplate.opsForValue().get("key2").toString();String result3 = redisTemplate.opsForValue().get("key3").toString();System.out.println("缓存结果为:result:" + result1 + " " + result2 + "  " + result3);return "缓存结果为:result:" + result1 + " " + result2 + "  " + result3;}/*** 保存和读取list*/@GetMapping("listredisdemo")public String listredisdemo() {List<String> list1 = new ArrayList<>();list1.add("a1");list1.add("a2");list1.add("a3");List<String> list2 = new ArrayList<>();list2.add("b1");list2.add("b2");list2.add("b3");redisTemplate.opsForList().leftPush("listkey1", list1);redisTemplate.opsForList().rightPush("listkey2", list2);List<String> resultList1 = (List<String>) redisTemplate.opsForList().leftPop("listkey1");List<String> resultList2 = (List<String>) redisTemplate.opsForList().rightPop("listkey2");System.out.println("resultList1:" + resultList1);System.out.println("resultList2:" + resultList2);return "成功";}/*** Hash结构,保存和读取map*/@GetMapping("mapredisdemo")public String mapredisdemo() {Map<String, String> map = new HashMap<>();map.put("key1", "value1");map.put("key2", "value2");map.put("key3", "value3");redisTemplate.opsForHash().putAll("map1", map);Map<String, String> resultMap = redisTemplate.opsForHash().entries("map1");List<String> reslutMapList = redisTemplate.opsForHash().values("map1");Set<String> resultMapSet = redisTemplate.opsForHash().keys("map1");String value = (String) redisTemplate.opsForHash().get("map1", "key1");System.out.println("value:" + value);System.out.println("resultMapSet:" + resultMapSet);System.out.println("resultMap:" + resultMap);System.out.println("resulreslutMapListtMap:" + reslutMapList);return "成功";}/*** 保存和读取Set*/@GetMapping("setredisdemo")public String getredisdemo() {SetOperations<String, String> set = redisTemplate.opsForSet();set.add("key1", "value1");set.add("key1", "value2");set.add("key1", "value3");Set<String> resultSet = redisTemplate.opsForSet().members("key1");System.out.println("resultSet:" + resultSet);return "resultSet:" + resultSet;}/*** 保存和读取zset*/@GetMapping("zsetredisdemo")public String zsetredisdemo() {ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<>("zset-5", 9.6);ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<>("zset-6", 9.9);Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();tuples.add(objectTypedTuple1);tuples.add(objectTypedTuple2);System.out.println(redisTemplate.opsForZSet().add("zset1", tuples));System.out.println(redisTemplate.opsForZSet().range("zset1", 0, -1));return "成功";}
}

序列化

直接粘贴在项目中即可

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*
*序列化*/
@Configuration
public class MyRedisConfig {@Bean(name = "redisTemplate")public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();//参照StringRedisTemplate内部实现指定序列化器redisTemplate.setConnectionFactory(redisConnectionFactory);redisTemplate.setKeySerializer(keySerializer());redisTemplate.setHashKeySerializer(keySerializer());redisTemplate.setValueSerializer(valueSerializer());redisTemplate.setHashValueSerializer(valueSerializer());return redisTemplate;}private RedisSerializer<String> keySerializer(){return new StringRedisSerializer();}//使用Jackson序列化器private RedisSerializer<Object> valueSerializer(){return new GenericJackson2JsonRedisSerializer();} 
}

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

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

相关文章

java仿聊天室项目总结_Java团队课程设计-socket聊天室(Day4总结篇)

Java团队课程设计-socket聊天室(Day4总结篇)团队名称&#xff1a;ChatRoom项目git地址&#xff1a;git提交记录(仅截取部分)&#xff1a;面向对象设计包图、类图包图UML类图总结&#xff1a;首先总结一下这几天遇到的问题和解决方案使用ObjectInputStream/ObjectOutputStream的…

python基础代码技巧_Python 代码优化技巧(二)

Python 是一种脚本语言&#xff0c;相比 C/C 这样的编译语言&#xff0c;在效率和性能方面存在一些不足&#xff0c;但是可以通过代码调整来提高代码的执行效率。本文整理一些代码优化技巧。 代码优化基本原则代码正常运行后优化。 很多人一开始写代码就奔着性能优化的目标&…

rpm 讲解

CentOS7主要有rpm和yum这两种包软件的管理。两种包的管理各有用处&#xff0c;其中主要区别是&#xff1a;YUM使用简单但需要联网&#xff0c;YUM会去网上的YUM包源去获取所需要的软件包。而RPM的需要的操作经度比较细&#xff0c;需要我们做的事情比较多。 软件包的安装和卸是…

java顺序表冒泡排序_冒泡排序就这么简单 - Java3y的个人空间 - OSCHINA - 中文开源技术交流社区...

冒泡排序就这么简单在我大一的时候自学c语言和数据结构&#xff0c;我当时就接触到了冒泡排序(当时使用的是C语言编写的)。现在大三了&#xff0c;想要在暑假找到一份实习的工作&#xff0c;又要回顾一下数据结构与算法的知识点了。排序对我们来说是一点也不陌生了&#xff0c;…

python 多线程和协程结合_如何让 python 处理速度翻倍?内含代码

阿里妹导读&#xff1a;作为在日常开发生产中非常实用的语言&#xff0c;有必要掌握一些python用法&#xff0c;比如爬虫、网络请求等场景&#xff0c;很是实用。但python是单线程的&#xff0c;如何提高python的处理速度&#xff0c;是一个很重要的问题&#xff0c;这个问题的…

python批量生成图_利用Python批量生成任意尺寸的图片

实现效果 通过源图片&#xff0c;在当前工作目录的/img目录下生成1000张&#xff0c;分别从1*1到1000*1000像素的图片。 效果如下&#xff1a;目录结构 实现示例 # -*- coding: utf-8 -*- import threading from PIL import Image image_size range(1, 1001) def start(): for…

Mysql 如果有多个可选条件怎么加索引_MySQL|mysql-索引

1、索引是什么 1.1索引简介 索引是表的目录&#xff0c;是数据库中专门用于帮助用户快速查询数据的一种数据结构。类似于字典中的目录&#xff0c;查找字典内容时可以根据目录查找到数据的存放位置&#xff0c;以及快速定位查询数据。对于索引&#xff0c;会保存在额外的文件…

java 全双工服务器_利用Java实现串口全双工通讯_JAVA实例教程_IT部落

本文介绍了一个简单的通过串口实现全双工通讯的Java类库&#xff0c;该类库大大的简化了对串口进行操作的过程一个嵌入式系统通常需要通过串口与其主控系统进行全双工通讯&#xff0c;譬如一个流水线控制系统需要不断的接受从主控系统发送来的查询和控制信息&#xff0c;并将执…

python语言三大基本控制结构_Python基础(4) 控制结构

三种控制流语句&#xff1a;if、for、while&#xff0c;Python用缩进表明成块的代码&#xff0c;以四个空格表示隶属关系&#xff0c;所以语句不能随意缩进。 1 条件语句 &#xff08;1&#xff09;简单的if语句 a 10 if a > 0: #末尾带“&#xff1a;” print(这是一个整数…

Spring-bean的循环依赖以及解决方式___Spring源码初探--Bean的初始化-循环依赖的解决

本文主要是分析Spring bean的循环依赖&#xff0c;以及Spring的解决方式。 通过这种解决方式&#xff0c;我们可以应用在我们实际开发项目中。 什么是循环依赖&#xff1f;怎么检测循环依赖Spring怎么解决循环依赖Spring对于循环依赖无法解决的场景Spring解决循环依赖的方式我们…

java+cache使用方法_java相关:springboot使用GuavaCache做简单缓存处理的方法

java相关&#xff1a;springboot使用GuavaCache做简单缓存处理的方法发布于 2020-3-29|复制链接摘记: 问题背景实际项目碰到一个上游服务商接口有10秒的查询限制(同个账号)。项目中有一个需求是要实时统计一些数据&#xff0c;一个应用下可能有多个相同的账号。由于服务商接口的…

python程序设计方法_Python程序设计现代方法

章Python概述001 1.1计算机与计算机语言002 1.1.1计算机的诞生与发展002 1.1.2计算机语言概述006 1.1.3翻译执行008 1.2Python语言概述009 1.2.1Python语言发展史009 1.2.2Python语言的特点011 1.2.3Python的应用领域012 1.2.4Python版本的区别012 1.3Python环境配置014 1.3.1安…

Spring中bean的作用域与生命周期

在Spring中&#xff0c;那些组成应用程序的主体及由Spring IoC容器所管理的对象&#xff0c;被称之为bean。简单地讲&#xff0c;bean就是由IoC容器初始化、装配及管理的对象&#xff0c;除此之外&#xff0c;bean就与应用程序中的其他对象没有什么区别了。而bean的定义以及bea…

pat乙级 1014 java_pat乙级1014 福尔摩斯的约会

大侦探福尔摩斯接到一张奇怪的字条&#xff1a;“我们约会吧&#xff01; 3485djDkxh4hhGE 2984akDfkkkkggEdsbs&hgsfdk d&Hyscvnm”。大侦探很快就明白了&#xff0c;字条上奇怪的乱码实际上就是约会的时间“星期四14:04”&#xff0c;因为前面两字符串中第1对相同的大…

python科学编程入门书_Python数据科学零基础一本通

领取成功 您已领取成功&#xff01; 您可以进入Android/iOS/Kindle平台的多看阅读客户端&#xff0c;刷新个人中心的已购列表&#xff0c;即可下载图书&#xff0c;享受精品阅读时光啦&#xff01; - | 回复不要太快哦~ 回复内容不能为空哦 回复已提交审核... 快登录帐号来一起…

python 整合excel_python EXcel表整合(自动办公)

收到任务&#xff0c;方便领导快速查看每个人的日程安排。比如每个工程师都有一个自己的表格记录自己的日程安排&#xff0c;领导查看每个人的日程安排需要一一打开所有工程师的日程安排表才能知道每个人的信息&#xff0c;而且非常不直观。 这里介绍下利用python解决实际办公问…

java poi 打开 保存_Java-Apache POI-在DB中读取和存储RTF内容

我们在Java应用程序中有一个新要求,即用户可以上传excel文件.excel文件中的一列将使用粗体,斜体,项目符号,彩色文本等格式.我们需要读取此excel文件并将这些值存储在Oracle DB表中.随后,我们还需要提取这些数据,并保留格式并下载到excel工作表中.我们计划将Apache-poi用于相同的…

Spring循环依赖的三种方式

引言&#xff1a;循环依赖就是N个类中循环嵌套引用&#xff0c;如果在日常开发中我们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用&#xff0c;直至内存溢出报错。下面说一下Spring是如果解决循环依赖的。 第一种&#xff1a;构造器参数循环依赖 Spring容…

python字典统计排序1_python-如何按字典顺序对Counter.mostCommon(n)的...

这里的问题是Counter dict是无序的,并且most_common不在乎键.为此,您需要对字典中的项目进行排序,然后提取最常见的3个项目. counter Counter(abcdef) most_common sorted(counter.items(), keylambda pair: (-pair[1], pair[0])) 这将首先对-pair [1](计数)进行排序.由于出现…

Java最后_Java最后一次总结

前言&#xff1a;最开始我学习了java如何简单编写一小段代码&#xff0c;发现java代码和C语言还是有很多相似的地方&#xff0c;到类与对象之后等等的很多的内容&#xff0c;我觉得还是有很大区别的&#xff0c;java对于c语言来说&#xff0c;显得更为高级及方便&#xff0c;让…