redisson常用APi-Example

2023-11-06

中文文档目录

redisson中文文档目录

分布式对象

package com.example.redissondemo.test;

import com.example.redissondemo.RedissonDemoApplication;
import com.example.redissondemo.test.domain.Order;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * 测试学习redisson 对象 api
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = RedissonDemoApplication.class)
@Slf4j
public class RedissonObjectExampleTests {

    @Autowired
    private RedissonClient redissonClient;


    /**
     * 直接存储对象,无需强制类型转换 (支持异步操作)
     */
    @Test
    public void bucketTest() {
        RBucket<Order> orderBucket = redissonClient.getBucket("myOrder");
        System.out.println("init : " + orderBucket.get());

        // 设置
        orderBucket.set(new Order(10L, "OR001"), 1, TimeUnit.MINUTES);
        System.out.println("设置 : " + orderBucket.get());

        // 删除
        System.out.println("删除状态:" + orderBucket.delete() + "当前" + orderBucket.get());

        // 重新设置
        orderBucket.set(new Order(10L, "OR001"), 1, TimeUnit.MINUTES);
        System.out.println("重新设置 : " + orderBucket.get());

        // 如果是or1 改为or2
        orderBucket.compareAndSet(new Order(10L, "OR001"), new Order(10L, "OR002"));
        System.out.println("存在or1 改为or2 : " + orderBucket.get());

        // 如果是or1 改为or3
        orderBucket.compareAndSet(new Order(10L, "OR001"), new Order(10L, "OR003"));
        System.out.println("存在or1 改为or3 : " + orderBucket.get());

        // 存在bucket对象就修改为OR3
        orderBucket.setIfExists(new Order(10L, "OR003"), 1, TimeUnit.MINUTES);
        System.out.println("存在bucket对象就修改为OR3 : " + orderBucket.get());

        orderBucket.isExists();

        orderBucket.delete();

    }

    /**
     * 数字操作,计数器 原子类操作 等等 (支持异步操作)
     *
     * @throws ExecutionException
     * @throws InterruptedException
     * @throws TimeoutException
     */
    @Test
    public void numberTest() throws ExecutionException, InterruptedException, TimeoutException {
        // 存在精度丢失
        RDoubleAdder doubleAdder = redissonClient.getDoubleAdder("doubleAdder");
        doubleAdder.add(1.9999);
        doubleAdder.add(2.0001);
        doubleAdder.add(3.0000000000000001);
        RFuture<Double> future = doubleAdder.sumAsync();
        Double sum = future.get(1000, TimeUnit.MILLISECONDS);
        System.out.println(sum);
        doubleAdder.delete();

        RLongAdder longAdder = redissonClient.getLongAdder("longAdder");
        longAdder.add(100);
        longAdder.increment();
        longAdder.increment();
        long longSum = longAdder.sum();
        System.out.println(longSum);
        longAdder.delete();
        longAdder.destroy();

        // 当不再使用整长型累加器对象的时候应该自行手动销毁,如果Redisson对象被关闭(shutdown)了,则不用手动销毁


        // 支持CAS设置
        RAtomicDouble atomicDouble = redissonClient.getAtomicDouble("atoDouble");
        double v = atomicDouble.incrementAndGet();
        System.out.println(v);

        atomicDouble.compareAndSet(v, 2.0);
        System.out.println(atomicDouble.get());
        atomicDouble.delete();

        RLongAdder atoLong = redissonClient.getLongAdder("atoLong");
        atoLong.increment();
        System.out.println(atoLong.sum());
        atoLong.delete();
    }

    /**
     * 限流*
     */
    @Test
    public void rateLimiterTest() {
        RRateLimiter limiter = redissonClient.getRateLimiter("orderImport");
        // 初始化
        // 最大流速 = 每1秒钟产生10个令牌
        // tryAcquire 尝试获取令牌
        // 如果令牌足够 则扣减令牌 返回true
        // 如果令牌不够 则不扣减  返回false

        // acquire 直接获取令牌 如果获取不到令牌 就阻塞等新的令牌产生
        // 如果令牌足够 则扣减对应的令牌
        // 如果令牌不够 则扣减令牌数量为0
        limiter.trySetRate(RateType.OVERALL, 10, 1, RateIntervalUnit.HOURS);

        boolean b = limiter.tryAcquire(1);
        System.out.println(" tryAcquire 1  availablePermits : " + limiter.availablePermits());
        b = limiter.tryAcquire(10);
        System.out.println(" tryAcquire 10 availablePermits : " + limiter.availablePermits());

        limiter.acquire(3);
        System.out.println("acquire 3 availablePermits : " + limiter.availablePermits());

        new Thread(() -> {
            limiter.acquire(2);
            System.out.println(" acquire 2 availablePermits : " + limiter.availablePermits());
        }).start();
        limiter.acquire(7);
        System.out.println(" acquire 7 availablePermits : " + limiter.availablePermits());

//        long start = System.currentTimeMillis();
        limiter.acquire(1);
//        System.out.println(System.currentTimeMillis() - start);
        System.out.println(" acquire 1 availablePermits : " + limiter.availablePermits());

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        limiter.acquire(7);
        System.out.println(" acquire 7 availablePermits : " + limiter.availablePermits());

        limiter.delete();
    }


    @Test
    public void mapDemo() {
//        RMap<String, String> test = redissonClient.getMap("test", MapOptions.defaults());
//        test.put("testKey", "testValue");
//        test.fastPut("fastTestKey", "testValue");
//        String testKey = test.get("testKey");
//        test.remove("testKey");
//        test.get("testKey");

        RBucket<MyBucket> myBucket = redissonClient.getBucket("myBucket");
        myBucket.set(new MyBucket(), 1, TimeUnit.MINUTES);
        System.out.println(myBucket.get());

        myBucket.rename("myBucket1");
        RBucket<MyBucket> myBucket1 = redissonClient.getBucket("myBucket");
        System.out.println(myBucket1.get());
        RBucket<MyBucket> myBucket2 = redissonClient.getBucket("myBucket1");
        System.out.println(myBucket2.get());

    }

    @Data
    public static class MyBucket {
        private String name = "test";
        private int age = 10;
    }


}

分布式集合

package com.example.redissondemo.test;

import com.alibaba.fastjson.JSONObject;
import com.example.redissondemo.RedissonDemoApplication;
import com.example.redissondemo.test.domain.Order;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 测试学习redisson 集合 api
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = RedissonDemoApplication.class)
@Slf4j
public class RedissonCollectionsExampleTests {

    @Autowired
    private RedissonClient redissonClient;


    /**
     *  Java对象实现了java.util.concurrent.ConcurrentMap接口和java.util.Map接口。与HashMap不同的是,RMap保持了元素的插入顺序。
     *  还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口
     *
     */
    @Test
    public void mapTest() throws ExecutionException, InterruptedException {
        String key = "user";
        RMap<String, String> map = redissonClient.getMap(key);
        map.put("name", "zhangsan");
        map.put("age", "18");

        String name = map.get("name");
        System.out.println ("user name : " + name);

        boolean b = map.containsKey("age");
        System.out.println("has age ? : " + b);

        Set<Map.Entry<String, String>> entries = map.entrySet();
        System.out.println(Arrays.toString(entries.toArray()));
        map.remove("age");

        // fastPut 和 put 的区别就是 put会发回之前该索引位置的值(如果存在) 而fastPut 只会返回插入成功与否
        map.fastPut("like", "eat");
        System.out.println(JSONObject.toJSONString(map));
        // 同理
        map.fastRemove("like");

        // 异步操作 提高操作效率
        RFuture<String> putAsyncFuture = map.putAsync("321","");
        RFuture<Boolean> booleanRFuture = map.fastPutAsync("123", "");

        putAsyncFuture.get();
        booleanRFuture.get();
        System.out.println(JSONObject.toJSONString(map));
    }

    /**
     * 多值映射 一对多映射关系的存储
     * 基于list  set
     */
    @Test
    public void myMultimapTest(){
        // 基于set 基于Set的Multimap不允许一个字段值包含有重复的元素。
        RSetMultimap<String, String> map = redissonClient.getSetMultimap("RSetMultimap");
        map.put("age", "19");
        map.put("age", "20");
        map.put("name", "zhangsan");

        Set<String> allValues = map.get("age");
        System.out.println(allValues);
        List<String> newValues = Arrays.asList("17", "16", "15");
        Set<String> oldValues = map.replaceValues("age", newValues);
        System.out.println(oldValues);
        Set<String> removedValues = map.removeAll("age");
        System.out.println(removedValues);

        map.put("carCount", "2");
        Set<Map.Entry<String, String>> entries = map.entries();
        System.out.println(JSONObject.toJSONString(entries));
        map.delete();

        // 基于list 同理 基于List的Multimap在保持插入顺序的同时允许一个字段下包含重复的元素。
        redissonClient.getListMultimap("myListMultimap");


        //  Multimap对象的淘汰机制是通过不同的接口来实现的。它们是RSetMultimapCache接口和RListMultimapCache接口,分别对应的是Set和List的Multimaps。
        RListMultimapCache<Object, Object> myListMultimap2 = redissonClient.getListMultimapCache("myListMultimap2");
        myListMultimap2.expireKey("2", 10, TimeUnit.MINUTES);

        RSetMultimapCache<Object, Object> getSetMultimapCache = redissonClient.getSetMultimapCache("getSetMultimapCache");
        getSetMultimapCache.expireKey("2", 10, TimeUnit.MINUTES);

    }

    /**
     * 基于Redis的Redisson的分布式Set结构的RSet Java对象实现了java.util.Set接口。
     */
    @Test
    public void baseSet(){
        RSet<Order> set1 = redissonClient.getSet("anySet");
        set1.add(new Order());
        set1.remove(new Order());


        // 基于Redis的Redisson的分布式RSetCache Java对象在基于RSet的前提下实现了针对单个元素的淘汰机制
        /**
         * 目前的Redis自身并不支持Set当中的元素淘汰,因此所有过期元素都是通过org.redisson.EvictionScheduler实例来实现定期清理的。
         * 为了保证资源的有效利用,每次运行最多清理100个过期元素。
         * 任务的启动时间将根据上次实际清理数量自动调整,间隔时间趋于1秒到2小时之间。
         * 比如该次清理时删除了100条元素,那么下次执行清理的时间将在1秒以后(最小间隔时间)。
         * 一旦该次清理数量少于上次清理数量,时间间隔将增加1.5倍。
         */

        RSetCache<Object> set2 = redissonClient.getSetCache("anySet2");
        // ttl = 10 seconds
        set2.add(new Order(), 10, TimeUnit.SECONDS);


        // 基于Redis的Redisson的分布式RSortedSet Java对象实现了java.util.SortedSet接口。在保证元素唯一性的前提下,通过比较器(Comparator)接口实现了对元素的排序。
        RSortedSet<Integer> set = redissonClient.getSortedSet("anySet");
        set.trySetComparator(Comparator.comparingInt(a -> a)); // 配置元素比较器
        set.add(3);
        set.add(1);
        set.add(2);

        set.removeAsync(0);
        set.addAsync(5);
    }


    @Test
    public void baseListAndQueue(){
        // 基于Redis的Redisson分布式列表(List)结构的RList Java对象在实现了java.util.List接口的同时,确保了元素插入时的顺序。
        RList<Order> list = redissonClient.getList("anyList");
        list.add(new Order());
        Order order = list.get(0);
        list.remove(new Order());


        // 队列
        RQueue<Order> queue1 = redissonClient.getQueue("anyQueue");
        // 双端队列(Deque
        RDeque<Order> queue2 = redissonClient.getDeque("anyDeque");
        // 阻塞队列(Blocking Queue)
        RBlockingQueue<Order> queue3= redissonClient.getBlockingQueue("anyQueue");
        // 有界阻塞队列(Bounded Blocking Queue)
        RBoundedBlockingQueue<Order> queue4 = redissonClient.getBoundedBlockingQueue("anyQueue");

        // 延迟队列(Delayed Queue)
        // 基于Redis的Redisson分布式延迟队列(Delayed Queue)结构的RDelayedQueue Java对象在实现了RQueue接口的基础上提供了向队列按要求延迟添加项目的功能。
        // 该功能可以用来实现消息传送延迟按几何增长或几何衰减的发送策略。
        RDelayedQueue<Order> delayedQueue = redissonClient.getDelayedQueue(queue1);

        // 优先队列(Priority Queue)
        RPriorityQueue<Integer> queue = redissonClient.getPriorityQueue("anyQueue");

    }

}

分布式锁

redisson分布式锁学习

private void redissonDoc() throws InterruptedException {
    //1. 普通的可重入锁
    RLock lock = redissonClient.getLock("generalLock");

    // 拿锁失败时会不停的重试
    // 具有Watch Dog 自动延期机制 默认续30s 每隔30/3=10 秒续到30s
    lock.lock();

    // 尝试拿锁10s后停止重试,返回false
    // 具有Watch Dog 自动延期机制 默认续30s
    boolean res1 = lock.tryLock(10, TimeUnit.SECONDS);

    // 拿锁失败时会不停的重试
    // 没有Watch Dog ,10s后自动释放
    lock.lock(10, TimeUnit.SECONDS);

    // 尝试拿锁100s后停止重试,返回false
    // 没有Watch Dog ,10s后自动释放
    boolean res2 = lock.tryLock(100, 10, TimeUnit.SECONDS);

    //2. 公平锁 保证 Redisson 客户端线程将以其请求的顺序获得锁
    RLock fairLock = redissonClient.getFairLock("fairLock");

    //3. 读写锁 没错与JDK中ReentrantLock的读写锁效果一样
    RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("readWriteLock");
    readWriteLock.readLock().lock();
    readWriteLock.writeLock().lock();
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

redisson常用APi-Example 的相关文章

  • 枚举的子类化

    有没有一种简单的方法来子类化Javaenum 我问这个问题是因为我有大约 10 个实现相同接口的对象 但它们对某些方法也有相同的实现 因此我想通过将所有相同的实现放置在扩展的中间对象中来重用代码Enum它也是我需要的所有其他类的超类 或许事
  • 连接外部 Accumulo 实例和 java

    我正在尝试使用 Accumulo 连接到虚拟机 问题是 我无法将其连接到 Java 中 我可以看到 Apache 抛出的网页 但我无法让它与代码一起工作 我认为这是缺乏知识的问题而不是真正的问题 但我找不到这方面的文档 所有示例都使用 lo
  • 使用 proguard 混淆文件名

    我正在使用 proguard 和 Android Studio 混淆我的 apk 当我反编译我的apk时 我可以看到很多文件 例如aaa java aab java ETC 但我项目中的所有文件都有原始名称 有没有办法混淆我的项目的文件名
  • 查看Java Agent修改的Java类的源代码

    我需要了解 Java 代理如何修改我的初始类 以便我能够理解代码的作用 build gradle configurations jar archiveName agent2 jar jar manifest attributes Prema
  • 通过Zuul上传大文件

    我在通过 zuul 上传大文件时遇到问题 我正在使用 apache commons 文件上传 https commons apache org proper commons fileupload https commons apache o
  • 有人用过 ServiceLoader 和 Guice 一起使用吗?

    我一直想通过我们的应用程序 构建系统进行更大规模的尝试 但更高的优先级不断将其推到次要地位 这似乎是加载 Guice 模块的好方法 并且避免了关于 硬编码配置 的常见抱怨 单个配置属性很少会自行更改 但您几乎总是会有一组配置文件 通常用于不
  • 如何使用 Java Apache POI 隐藏 Excel 工作表中以下未使用的行?

    我正在使用数据库中的数据填充模板 Excel 工作表 for Map
  • getCurrentSession 在网络中休眠

    我正在使用 hibernate 和 jsp servlet 编写一个基于 Web 的应用程序 我读过有关sessionFactory getCurrentSession and sessionFactory openSession方法 我知
  • ThreeTen 向后移植与 JSR-310 的比较

    由于某些原因 我们现在无法使用 java 8 我们仍然停留在 java 7 上 不过 我想使用新的JSR 310 date time APIs现在 使用官方向后移植 ThreeTen http www threeten org threet
  • 如何在 IntelliJ IDEA 中运行 akka actor

    来自 Akka 网站文档 然后 这个主要方法将创建所需的基础设施 运行演员 启动给定的主要演员并安排 一旦主要参与者终止 整个应用程序就会关闭 因此 您将能够使用类似于以下的命令运行上面的代码 下列的 java classpath akka
  • 在java程序中使用c++ Dll

    我正在尝试使用System LoadLibrary 使用我用 C 编写的一个简单的 dll UseDllInJava java import com sun jna Library import com sun jna Native imp
  • IntelliJ Idea:将简单的 Java servlet(无 JSP)部署到 Tomcat 7

    我尝试按照教程进行操作here http wiki jetbrains net intellij Creating a simple Web application and deploying it to Tomcat部署 servlet
  • 如何向页面添加 HTML 页眉和页脚?

    如何使用 itext 从 html 源添加标题到 pdf 目前 我们已经扩展了 PdfPageEventHelper 并重写了这些方法 工作正常 但当我到达 2 个以上页面时 它会抛出 RuntimeWorkerException Over
  • Lombok 不适用于 Eclipse Neon

    我下载了lombok jar lombok 1 16 14 jar 并将其放入我的下载中 然后我点击这个 jar 执行正确地识别了我的 MacOS 上的 Eclipse 实例 然后我选择了我想要的实例 Lombok也在pom xml中指定
  • Android ScrollView,检查当前是否滚动

    有没有办法检查标准 ScrollView 当前是否正在滚动 方向是向上还是向下并不重要 我只需要检查它当前是否正在滚动 ScrollView当前形式不提供用于检测滚动事件的回调 有两种解决方法可用 1 Use a ListView并实施On
  • Selenium 单击在 Internet Explorer 11 上不起作用

    我尝试在 Internet Explorer 上单击 selenium 但它不起作用 我努力了element click moveToElement element click build perform javascript没事了 事实上
  • 如何让 Firebase 与 Java 后端配合使用

    首先 如果这个问题过于抽象或不适合本网站 我想表示歉意 我真的不知道还能去哪里问 目前我已经在 iOS 和 Android 上开发了应用程序 他们将所有状态保存在 Firebase 中 因此所有内容都会立即保存到 Firebase 实时数据
  • Java 的“&&”与“&”运算符

    我使用的示例来自 Java Herbert Schildt 的完整参考文献 第 12 版 Java 是 14 他给出了以下 2 个示例 如果阻止 第一个是好的 第二个是错误的 因此发表评论 public class PatternMatch
  • Spring 作为 JNDI 提供者?

    我想使用 Spring 作为 JNDI 提供程序 这意味着我想在 Spring 上下文中配置一个 bean 可以通过 JNDI 访问该 bean 这看起来像这样
  • GAE 无法部署到 App Engine

    我正在尝试从 Eclipse 发布 Web 应用程序 我在 GAE 上创建了四个项目 可以通过登录我的帐户并查看控制台来查看它们 我已经改变了appengine web xml到项目的应用程序 ID 如果我将其更改为 GAE 上第一个创建的

随机推荐

  • ws协议与http协议的异同

    http协议 识别数据内容 与webSocket协议 同 建立在TCP之上 同http一样通过TCP来传输数据 不同 HTTP协议为单向协议 即浏览器只能向服务器请求资源 服务器才能将数据传送给浏览器 而服务器不能主动向浏览器传递数据 分为
  • Selenium及chromedriver安装教程

    文章目录 安装Python环境及Selenium工具包 使用命令行安装 使用Pycharm安装 安装chromedriver驱动 验证 安装Python环境及Selenium工具包 首先 我们需要安装Python环境 安装好了之后需要安装S
  • keras IMDB数据集 LSTM分类

    在keras提供的IMDB数据集中 word被映射为一个大于0的整数 表示该单词出现频率的排名 这样处理的目的是为了方便按照词频过滤单词 其中0用于表示unknown word 载入数据 x train shape 25000 是一个250
  • 如果IBM再给我一次实习机会

    2014年 我拿到了IBM斯图加特R D的实习机会 在连续被索尼和博世拒掉之后 这个实习对我来说弥足珍贵 我学的是通信专业 在这之前与编程相关的活动只有一学期的安卓Lab 还是靠抱队友大腿才及格 在申请时 我的编程能力可以说几乎为0 连我自
  • java: 找不到符号 符号: 类 ResourceVO 位置: 类 com.

    一 java找不到符号 如果你的代码里没有任何问题 但是java报错找不到符号 如下 解决方法
  • 《Pytorch深度学习和图神经网络(卷 2)》学习笔记——第二章

    基于图片内容的处理任务 主要包括目标检测 图片分割两大任务 目标检测 精度相对较高 主要是以检测框的方式 找出图片中目标物体所在坐标 模型运算量相对较小 相对较快 图片分割 精度相对较低 主要是以像素点的集合方式 找出图片中目标物体边缘的具
  • Prometheus 监控之 kafka

    初探 默认情况下 Kafka metrics 所有的 metric 都可以通过 JMX 获取 暴露kafka metrics 支持两种方式 1 在 Kafka Broker 外部 作为一个独立进程 通过 JMX 的 RMI 接口读取数据 这
  • linux:需要注意docker和aws的rds的mysql默认是UTC而不是中国时区

    问题 如题 解决办法 docker参考 mysql时间不对 修改时区 set global time zone 无效 小书生 的博客 CSDN博客 aws参考 https www youtube com watch v B NaqV A1B
  • 数字IC手撕代码--联发科(总线访问仲裁)

    题目描述 当A B两组的信号请求访问某个模块时 为了保证正确的访问 需要对这些信号进行仲裁 请用Verilog实现一个仲裁器 对两组请求信号进行仲后 要求 协议如图所示 请求方发送req request 信号1表示有请求给仲裁器 仲裁器响应
  • es6扩展运算符 (...)

    es6的扩展运算符就是取出参数对象中的所有可遍历属性 拷贝到当前对象之中 let bar a 1 b 2 let baz bar a 1 b 2 实际上是通过Object assign方法实现的 let baz Object assign
  • 【React】路由懒加载 React.lazy()

    React路由懒加载lazy 文章目录 React路由懒加载lazy React lazy 懒加载概念 React lazy 使用 React lazy 懒加载概念 我们在使用网站时 如果不对路由使用懒加载 则会导致刚打开网站就加载全部路由
  • spring security oauth2源码解析

    spring security oauth2源码解析 EnableResourceServer 启用资源服务配置 注入配置 ResourceServerConfiguration ResourceServerConfiguration 资源
  • 利用ThreadPoolTaskExecutor创建线程池,并实现数据透传

    1 线程池配置 Configuration public class ThreadPoolConfig cpu内核 暂时默认8核 private static final int CORE SIZE 8 核心线程数 暂定为I O密集型 pr
  • java 取出list 中一列_java8新特性 获取list某一列的操作

    提取某一列 以name为例 从对象列表中提取一列 以name为例 List nameList studentList stream map StudentInfo getName collect Collectors toList 提取后输
  • 大数据毕设项目 大数据电影数据分析与可视化系统 - python Django

    文章目录 0 前言 1 课题背景 2 效果实现 3 爬虫及实现 4 Flask框架 5 Ajax技术 6 Echarts 7 最后 0 前言 这两年开始毕业设计和毕业答辩的要求和难度不断提升 传统的毕设题目缺少创新和亮点 往往达不到毕业答辩
  • 字符串版本号比较(Java)

    APP的版本升级更新 会用到版本号的对比 根据版本号去解析埋点上报得信息 正则匹配方式解析版本号中字符和数字做对比 默认字符大于数字 版本号1 是否大于等于 版本号2 详见以下代码 Slf4j public class CompareUti
  • java修饰符权限

    java修饰符有public protected private和default 默认 四种访问级别 四类修饰符都用于类 类属属性及方法 1 访问权限 访问权限 类 包 子类 其他包 备注 public 可 可 可 可 包内及包外的任何类均
  • 锟斤拷?UTF-8与GBK互转,为什么会乱码?

    作为一名程序员 肯定有被乱码困扰的时候 真到了百思不得其解的时候 就会觉得 英文程序员真幸福 但其实只要明白编码之间的转换规律 其实乱码so easy 我们知道 计算机存储数据都是2进制 就是0和1 那么这么多的字符就都需要有自己对应的0和
  • Android 之 Fragment 精讲 —— 底部导航栏的实现 (方法1)

    本节引言 在上一节中我们对Fragment进行了一个初步的了解 学习了概念 生命周期 Fragment管理与 Fragment事务 以及动态与静态加载Fragment 从本节开始我们会讲解一些Fragment在实际开发 中的一些实例 而本节
  • redisson常用APi-Example

    中文文档目录 redisson中文文档目录 分布式对象 package com example redissondemo test import com example redissondemo RedissonDemoApplicatio