Gradle(一)安装配置

Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。面向Java应用为主。当前其支持的语言限于Java、Groovy、Kotlin和Scala。 到此不得不说另一个很火的工具maven,众所周知,maven的两大作用: ①:管理jar包 ②:构建项目 使用maven的缺点,XML配置文件的繁琐,特别是项目较大时,pom.xml配置眼花缭乱。 Gradle在maven的基础上,简化了配置文件,自动搜索Gradle等,使得我们创建管理项目更加简单。   一、下载,Gradle是压缩文件,下载解压即可。https://gradle.org/releases/ 这个是发布版,当然你还可以去 https://services.gradle.org/ 下载更新的版本。本人下载5.2.1的发布版 https://gradle.org/next-steps/?version=5.2.1&format=all 下载完毕后在本地目录解压即可。   二、配置环境变量:GRADLE_HOME 变量值为Gradle文件解压的实际路径,本文为例:E:\Gradle\gradle-5.2.1-all\gradle-5.2.1 在系统变量 path中加入:%GRADLE_HOME%\bin; 在cmd输入gradle -v验证是否安装成功   三、配置Gradle使用maven本地仓库,这样Gradle就不会重新下载已经存在maven本地仓库的jar包,从而节省时间和空间。 在环境变量中加入新的系统变量:GRADLE_USER_HOME  变量值是maven本地仓库的路径,本文为例C:\Users\Administrator\.m2\repository 此时,Gradle下载的文件将放到指定的仓库路径中。但是还需要修改build.gradle文件中加入mavenLocal() 引用本地仓库 repositories { //repositories闭包 mavenLocal() //配置先从本地仓库寻找jar包,优先寻找上一个配置,找到不执行下面的配置 mavenCentral() //配置从中央仓库寻找 google() //第三方仓库 jcenter() //代码托管库:设置之后可以在项目中轻松引用jcenter上的开源项目 }   from:https://www.cnblogs.com/zeussbook/p/10556025.html

Maven安装与配置

一、需要准备的东西 1. JDK 2. Eclipse 3. Maven程序包 二、下载与安装 1. 前往https://maven.apache.org/download.cgi下载最新版的Maven程序: 2. 将文件解压到D:\Program Files\Apache\maven目录下: 3. 新建环境变量MAVEN_HOME,赋值D:\Program Files\Apache\maven 4. 编辑环境变量Path,追加%MAVEN_HOME%\bin\; 5. 至此,maven已经完成了安装,我们可以通过DOS命令检查一下我们是否安装成功:

三、配置Maven本地仓库 1. 在D:\Program Files\Apache\目录下新建maven-repository文件夹,该目录用作maven的本地库。 2. 打开D:\Program Files\Apache\maven\conf\settings.xml文件,查找下面这行代码:

localRepository节点默认是被注释掉的,需要把它移到注释之外,然后将localRepository节点的值改为我们在3.1中创建的目录D:\Program Files\Apache\maven-repository。 3. localRepository节点用于配置本地仓库,本地仓库其实起到了一个缓存的作用,它的默认地址是 C:\Users\用户名.m2。 当我们从maven中获取jar包的时候,maven首先会在本地仓库中查找,如果本地仓库有则返回;如果没有则从远程仓库中获取包,并在本地库中保存。 此外,我们在maven项目中运行mvn install,项目将会自动打包并安装到本地仓库中。 4. 运行一下DOS命令

如果前面的配置成功,那么D:\Program Files\Apache\maven-repository会出现一些文件。 四、配置Eclipse的Maven环境 1. Eclipse Oxygen,打开Window->Preferences->Maven->Installations,右侧点击Add。 2. 设置maven的安装目录,然后Finish 3. 选中刚刚添加的maven,并Apply。 4. 打开Window->Preferences->Maven->User Settings,配置如下并Apply: 至此,Maven的安装和配置全部结束。   from:https://www.cnblogs.com/eagle6688/p/7838224.html

开发人员正从 Java 8 向 Java 11 转移

此前的 Java 社区报告曾指出,Java 8 仍是开发人员使用的主要版本,新版本并未“得宠”。但 Snyk 近期发布的  JVM Ecosystem Report 2021 则指出,开发人员已经逐渐从 Java 8 迁移到了 Java 11。 JVM Ecosystem Report 2021 展示了关于 JVM 生态系统状态的最大年度调查的结果。该调查在 2021 年 2 月和 3 月的六周时间里进行,收集了来自 2000 多名 Java 开发者的回复。 调查结果显示,有 44.1% 的受访者在生产中使用免费的 AdoptOpenJDK 发行版。但 Oracle 仍然是市场上的重要参与者,其 OpenJDK 构建占 28%,商业 Oracle JDK 占 23%。 40% 的调查参与者在生产中使用了一个以上的 Java 版本。升级到 8 版本以上的人也比预料的要多。目前,有 61.5% 的人在生产中使用 Java 11,近 12% 的人使用最新版本,即调查期间的 Java 15。 Snyk 方面在报告中指出,这表明开发人员确实将他们的 Java 版本升级到了 Java 8 以上的版本,有关大多数 Java 开发人员都乐于使用 Java 8 的现象似乎正在慢慢瓦解。不过值得注意的是,仍有一半的 Java 11 用户(目前使用最多的版本)在他们的生产堆栈中使用 Java 8。 从长远来看,虽然 JVM 语言的种类在过去几年中有所增长,但 Java 仍然是最受欢迎的语言。超过 90% 的开发者使用 Java;Kotlin 次之,为 17.7%。 而 JetBrains IntelliJ IDEA 依旧是 Java 生态系统最主要的 IDE,有超过 70% 的 JVM 开发人员使用 IntelliJ IDEA。同时,Visual Studio Code 和 Apache Netbeans 的采用也有了巨大的增长。报告发现,有一半以上的 JVM 社区都认为适合使用多个 IDE。 Maven 仍然是 Java 生态系统的第一大构建系统,有超过 76% 的开发人员使用 Maven,这一比例甚至高于去年的调查。Gradle 则以 38.1% 的比例稳居第二,得分也高于去年。 此外,Spring 仍然主导着 Java 生态系统,Spring Boot 和 Spring MVC 是 JVM 最主要的框架。一半以上的市场使用 Spring Boot,几乎三分之一的市场使用 Spring MVC。Snyk 称,“总的来说,我们看到我们生活在一个由 Spring 高度主导的世界,这似乎表明 Spring 的人在为社区服务方面做得很好。” 完整报告地址:https://snyk.io/jvm-ecosystem-report-2021/   from:https://www.oschina.net/news/149523/jvm-ecosystem-report-2021

java.security.egd

SecureRandom在java各种组件中使用广泛,可以可靠的产生随机数。但在大量产生随机数的场景下,性能会较低。这时可以使用"-Djava.security.egd=file:/dev/./urandom"加快随机数产生过程。 以产生uuid的时候使用nextBytes产生随机数为入口,xSecureRandom的代码逻辑。

使用了SecureRandom.next*的方法。 在使用SecureRandom产生下一个随机数的时候调用nextLong或者nextBytes,最终会调用SecureRandom的nextBytes。

而nextBytes是一个同步的方法,在多线程使用时,可能会产生性能瓶颈。

  secureRandomSpi被初始化为sun.security.provider.SecureRandom secureRandomSpi是SecureRandom.NativePRNG的一个实例。 使用jvm参数-Djava.security.debug=all ,可以打印securityprovider列表,从中可以看出,SecureRandom.NativePRNG由sun.security.provider.NativePRNG提供服务。 Provider: Set SUN provider property[SecureRandom.NativePRNG/sun.security.provider.NativePRNG]   分析openjdk的源码,NativePRNG.engineNextBytes调用了NativePRNG.RandomIO.ensureBufferValid,而ensureBufferValid直接从urandom读取数据:

  通过测试可以发现,hotspot需要使用配置项"-Djava.security.egd=file:/dev/./urandom"才能从urandom读取数据,这里openjdk做了优化,直接从urandom读取数据。 /dev/random在产生大量随机数的时候比/dev/urandom慢,所以,建议在大量使用随机数的时候,将随机数发生器指定为/dev/./urandom。   转自:https://blog.51cto.com/leo01/1795447   from:https://blog.csdn.net/wangooo/article/details/109139129

如何用Docker打包Springboot的四种方式

一:最基本的Dockerfile构建Springboot项目 在pom同目录下新建Dockerfile

  将Springboot使用Maven打包,在终端中传参进去,进行构建Images。

  给Springboot启动时候传环境变量或者shell参数

  指定JVM参数和shell参数

  二:使用Idea可视化管理docker, 构建Springboot容器 这个在我另外一篇文章有讲到,都比较简单,有啥问题请留言。 三:使用Maven插件自动化构建Image https://github.com/spotify/dockerfile-maven ,能力强的可以直接去看README.md。 简单介绍一下这个插件做啥用的 通过pom配置docker构建Image过程,参数等 。 封装了自动化build,push,run等Maven命令 。 * 需要依赖Dockerfile,Dockerfile与pom.xml位于同一个目录下。 在pom.xml同目录下创建Dockerfile

  在pom中添加

  最后在Idea Maven插件Plugins点击docker:build即可。或者输入命令

  四:使用Google的Maven插件进行容器管理(重头戏) Google开源项目Jib,对比上面那个插件Jib的Start数为7.8k,dockerfile-maven 为2.4k。 maven 插件

  配置maven docker hub账户和密码,在maven settings.xml中添加

  在idea maven插件中点击或者maven命令 mvn compile jib:buildTar 可以看到推送远程成功,Jib不需要写Dockerfile只需要你在插件中定义构建类型,所以使用时请多参考github的文档。最后现在也有这种开源的容器云平台,可以去了解下。   from:https://zhuanlan.zhihu.com/p/89161347

SpringBoot 部署 docker 打包镜像

环境: 1、代码编写工具:IDEA 2、打包:maven 3、docker 4、linux 7、JDK1.8 8、Xshell 9、Xftp 第一步:使用idea创建简单的springboot项目 第二步:设置项目生成jar包(两种方式) 1、修改pom文件

2、或者在生成项目的时候 可以选择jar和war 第三步:使用maven 生成包 (使用idea不用命令 直接界面操作就可以(如果Maven设置没问题 直接就可以生成 包 log会提示生成后的文件目录))   第四步:docker概念 1、docker:最早是dotCloud公司出品的一套容器管理工具,但后来Docker慢慢火起来了,连公司名字都从dotCloud改成Docker。 2、dockerfile:它是Docker镜像的描述文件,可以理解成火箭发射的A、B、C、D……的步骤。 3、docker镜像:通过Dockerfile做出来的,包含操作系统基础文件和软件运行环境,它使用分层的存储方式。 4、docker容器:是运行起来的镜像,简单理解,Docker镜像相当于程序,容器相当于进程。 第四步:dockerfile指令 Dockerfile由多条指令组成,每条指令在编译镜像时执行相应的程序完成某些功能,由指令+参数组成,以逗号分隔,#作为注释起始符,虽说指令不区分大小写,但是一般指令使用大些,参数使用小写 第五步:dockerfile文件例子(我只是简单将springboot项目生成docker镜像没有什么多余配置) TODO:有一点需要注意的地方就是dockerfile文件没有任何后缀

第六步:将dockerfile文件和生成好的jar 使用ftp工具上传到linux服务器 随便找个文件夹 放进去 jar和dockerfile在同级目录下 第七步:使用 docker build -t ordinary:v1.0 . TODO: 1、 最后面的这个 . 代表在当前目录下面寻找 dockerfile 文件 2、ordinary 镜像名字 3、v1.0版本 第八步:查看镜像及启动 1、使用docker images 来查看生成的镜像 2、使用docker create 来创建容器 docker run 来创建并且运行容器 3、也可以使用docker logs 容器名 --tail 100 -f 来查看项目启动日志 看项目是否启动 3、如果上面步骤一切正常 可以直接调用IP加端口来访问项目 通过Docker run命令定义Spring Profile 可以将spring profile作为环境变量传递给docker run命令,使用 -e 标记。 例如 -e “SPRING_PROFILES_ACTIVE=dev”会将dev profile传递给Docker容器 docker run -d -p 8080:8080 -e "SPRING_PROFILES_ACTIVE=dev" --name rest-api dockerImage:latest   from:https://www.thinbug.com/q/13555214

Docker部署SpringBoot项目

1.创建springboot项目   创建springboot项目

  2.打包springboot项目为jar包 3. 编写Dockerfile文件

  解释下这个配置文件: VOLUME 指定了临时文件目录为/tmp。其效果是在主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp。该步骤是可选的,如果涉及到文件系统的应用就很有必要了。/tmp目录用来持久化到 Docker 数据文件夹,因为 Spring Boot 使用的内嵌 Tomcat 容器默认使用/tmp作为工作目录 项目的 jar 文件作为 “app.jar” 添加到容器的 ENTRYPOINT 执行项目 app.jar。为了缩短 Tomcat 启动时间,添加一个系统属性指向 “/dev/./urandom” 作为 Entropy Source 如果是第一次打包,它会自动下载java 8的镜像作为基础镜像,以后再制作镜像的时候就不会再下载了。 4. 部署文件 在服务器新建一个docker文件夹,将maven打包好的jar包和Dockerfile文件复制到服务器的docker文件夹下 docker文件夹 5. 制作镜像 执行下面命令, 看好,最后面有个"."点!

  -t 参数是指定此镜像的tag名 制作完成后通过docker images命令查看我们制作的镜像 6.启动容器

  7. 访问网站 直接浏览器访问: http://你的服务器ip地址:8080/ 好了,下一步就是学习springboot+mysql+redis如何在docker上如何部署了。 作者:雄关漫道从头越 链接:https://www.jianshu.com/p/397929dbc27d 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

spring boot服务docker镜像优化之旅

缘由 我们在使用spring boot开发的服务中,一般会选择打包成单体的fatjar来发布服务,这在传统的部署方式下是非常方便的,但是当我们选择使用docker这种容器化的方式来部署应用的时候,却有一点点的不便之处,因为这个单体的jar一般都比较大,每次镜像push到仓库和从仓库拉取都需要比较长的时间。 原因是什么了? docker的一大特色就是镜像的存储是分层的,参考下面这张官图 我们在Dockerfile中的每一个指令会对应到镜像的每一层,docker在更新镜像时,只会推送变更过的层,当它计算出来这一层的摘要和之前的版本一致时,会复用上一次打包镜像时的缓存,会极大的提高打包镜像以及镜像push/pull操作的速度。 那么问题来了,当我们springboot打包出来的单体jar的时候,每次编译这个jar都会发生变化,对应的存储层也会发生变化,push和pull操作时都需要重新推送,而且这个jar一般都不小,一个典型的应用会在100M左右,对应用部署和发布的速度会有比较大的影响。 稍作思考,很容易就能发现这个肥大的jar文件里面,大部分其实都是固定不变的各种依赖库,我们真正每次编译会变化的业务代码部分其实很小很小,可能也就只有几百KB,只要能将这两部分分离,变成docker镜像中的两层,一定能极大的提升镜像发布的速度 牛刀小试 首先拿来动手尝试的是一个springboot admin的项目,项目的结构是这样的: 使用最常见的打包方式:

会生成一个32M的jar文件,优化之前的Dockerfile非常简单:

  可以看到这种方式在构建v2版本的镜像时,会重新copy整个完整的jar 如果要拆开这个单体的jar,有两种方式,一是修改mvn打包的配置,将lib包放在独立的文件夹下,在这里我们考虑到项目众多,尽量减少修改,选择了在Docker打包镜像时,解压打包出来的jar包,将其中的内容分开来copy,修改后的Dockerfile如下:

  看看修改后的效果: 在copy lib目录时,是直接using cache的。来看看push的时候效果对比 首先是优化前的push: 可以看到在push v2的时候还是会push一个33MB的层,虽然其实我们一行代码没有修改。 然后是优化后的: 可以看到这一次仅仅只推送了一个13KB的层,推送的速度快了非常多,同理也可以想象的到,我们在拉取镜像更新版本时速度会快很多。 路遇荆棘 在针对springboot-admin这个最简单的项目的优化取得很好的效果之后,就开始准备照搬到其他的项目中,没想到同样的方式怎么折腾都无效,分离之后的lib目录依然会每次需要全量重新push。出问题的项目结构大概是这样的: 一个常见的多模块mvn项目,有common,domain,rest-client,rest-server 这4个子模块,其中rest-server会依赖common和domain这两个子模块,打包出来的jar是在rest-server这个模块中。 究竟是什么鬼了? 终得正果 苦苦思索一番之后,lib目录既然不能复用上一次的cache,那一定是因为里面的内容有变化,遂将jar包解压,进到lib目录,真凶果然在此: 项目自身的3个子模块在每次编译的时候也会做为jar包放到lib目录下,这3个jar包每次编译都会有变化,所以导致这一层的cache失效。 找到问题之后,解决的思路就很简单了,将这种jar单独copy到一个目录下即可,修改后的Dockerfile如下:

  这样修改之后效果就和上面单模块的项目一样了,至此,基本完成了springboot项目的docker镜像优化,在jenkins的流水线上可以将原来镜像push的时间从1分钟以上优化到10s左右 未来之路 在整个优化的过程中,发现springboot2.3 M1版本已经有针对性的优化方案,增加了LAYERED_JAR的打包格式,未来可期。 具体可参考下文: www.jdon.com/53738 注: 本文中举例的两个项目案例,可在github上找到:github.com/yishh/sprin… 作者:thor_lee 链接:https://juejin.cn/post/6844904119338008583 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

docker springboot项目镜像优化

遇到的问题: 公司java项目按老的方式打包出来一个fat jar,100MB, 推送到腾讯云镜像仓库很慢,8分钟。。。走的是公网,专线暂时还没配置好 以前是内网harbor,速度还不明显。 归根究底,一次推送100MB是个不合理的事情 思路: 了解spring boot打包,期望将依赖的libs 和 业务代码拆分 优化dockerfile,充分利用缓存   解决问题: 先修改spring-boot-maven-plugin,只打包业务代码。网上有些是配置exclude,我试了,恶心到了。。那么多包挨个找

  新增maven-dependency-plugin,将依赖移到libs目录下

  优化dockerfile 参考 https://medium.com/@nieldw/caching-maven-dependencies-in-a-docker-build-dca6ca7ad612 ,牛逼

  搞定。最终代码变化每次推送也就1MB多 启动命令 java -Dloader.path="libs/" -jar app.jar 作者:小猋_a8f1 链接:https://www.jianshu.com/p/32456eea0488 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Guava 快速入门(一)

Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。   Guava 是Java的工具集,提供了一些常用的便利的操作工具类,减少因为 空指针、异步操作等引起的问题BUG,提高开发效率。 本文主要介绍了Guava常用的工具方法,快速入门Guava。 1、基本工具(Base utils) 1. Optional null 值出现在代码中,有如下缺点: 语义模糊,引起歧义。例如,Map.get(key)返回Null时,可能表示map中的值是null,亦或map中没有key对应的值。 在应用层面可能造成混乱,出现令人意外的错误。 为了尽量避免程序中的null值,guava提供了Optional对数据进行封装。如果值为空则立即抛出异常,并且提供了Absent和Present两个子类分别表示值缺失和值存在的情形,来增强null的语义。 常用方法如下: isPresent():如果Optional包含非null的引用(引用存在),返回true get() :如果Optional为NULL将触发异常

or(defaultvalue) :包含的引用缺失(null),返回默认的值,否则返回本身 orNull():包含的引用缺失,返回null asSet():如果引用存在,返回只有单一元素的集合;若为NULl返回空集合 2. 先决条件 Preconditions Preconditions 提供了判断条件是否合法的静态方法,如果不符合要求会抛出异常。类似断言。 方法声明(不包括额外参数) 描述 检查失败时抛出的异常 checkArgument(boolean) 检查boolean是否为true,用来检查传递给方法的参数 IllegalArgumentException checkNotNull(T) 检查value是否为null,该方法直接返回value,因此可以内嵌使用checkNotNull NullPointerException checkState(boolean) 用来检查对象的某些状态。 IllegalStateException checkElementIndex(int index, int size) 检查index作为索引值对某个列表、字符串或数组是否有效。index>=0 && index<size IndexOutOfBoundsException checkPositionIndex(int index, int size) 检查index作为位置值对某个列表、字符串或数组是否有效。index>=0 && index<=size IndexOutOfBoundsException checkPositionIndexes(int start, int end, int size) 检查[start, end]表示的位置范围对某个列表、字符串或数组是否有效 IndexOutOfBoundsException 每个判断方法都有三个多态方法: 没有额外参数:抛出的异常中没有错误消息; 有一个Object对象作为额外参数:抛出的异常使用Object.toString() 作为错误消息; 有一个String对象作为额外参数,并且有一组任意数量的附加Object对象:这个变种处理异常消息的方式有点类似printf,但考虑GWT的兼容性和效率,只支持%s指示符。例如:

  3. 连接器 Joiner 用分隔符将多个字符串(或数组元素)连接成一个字符串。 常用方法如下: on(String):静态工厂方法,生成一个新的 Joiner 对象,参数为连接符 skipNulls():如果元素为空,则跳过 useForNull(String):如果元素为空,则用这个字符串代替 join(数组/链表):要连接的数组/链表 appendTo(String,数组/链表):在第一个参数后面新加上 拼接后的字符串 withKeyValueSeparator(String):得到 MapJoiner,连接Map的键、值

  输出:

注意:joiner实例总是不可变的。用来定义joiner目标语义的配置方法总会返回一个新的joiner实例。这使得joiner实例都是线程安全的,你可以将其定义为static final常量。   4. 拆分器 Splitter Splitter 能将一个字符串按照分隔符生成字符串集合,是 Joiner的反向操作。 常用方法如下: on(String):静态工厂方法,生成一个新的 Splitter 对象,参数为连接符 trimResults():结果去除子串中的空格 omitEmptyStrings():去除null的子串 split(String):拆分字符串 withKeyValueSeparator(String):得到 MapSplitter,拆分成Map的键、值。注意,这个对被拆分字符串格式有严格要求,否则会抛出异常

  输出如下:

  5. 字符串处理 Strings Strings 类主要提供了对字符串的一些操作。主要方法如下: nullToEmpty(String string) :null字符串转空字符串 emptyToNull(String string):空字符串转null字符串 isNullOrEmpty(String string):判断字符串为null或空字符串 padStart(String string, int minLength, char padChar):如果string的长度小于minLeng,在string前添加padChar,直到字符串长度为minLeng。

String padEnd(String string, int minLength, char padChar):和padStart类似,不过是在尾部添加新字符串 commonPrefix(CharSequence a, CharSequence b):返回共同的前缀 commonSuffix(CharSequence a, CharSequence b):返回共同的后缀

  输出如下:

  2、集合工具(Collections) 1. 不可变集合 不可变集合,即创建后就只可读,不可修改的集合。为什么要使用不可变集合呢?主要有如下优点(摘自官方文档): 当对象被不可信的库调用时,不可变形式是安全的; 不可变对象被多个线程调用时,不存在竞态条件问题 不可变集合不需要考虑变化,因此可以节省时间和空间。所有不可变的集合都比它们的可变形式有更好的内存利用率(分析和测试细节); 不可变对象因为有固定不变,可以作为常量来安全使用。 JDK也提供了Collections.unmodifiableXXX方法把集合包装为不可变形式,但我们认为不够好: 笨重而且累赘:不能舒适地用在所有想做防御性拷贝的场景; 不安全:要保证没人通过原集合的引用进行修改,返回的集合才是事实上不可变的;

  低效:包装过的集合仍然保有可变集合的开销,比如并发修改的检查、散列表的额外空间,等等。 注意:所有Guava不可变集合的实现都不接受null值。因为谷歌内部调查代码发现,只有5%的情况需要在集合中允许null元素。如果要存储null值,请使用JDK的Collections.unmodifiable方法 创建不可变集合的几个方法: copyOf 方法,如ImmutableSet.copyOf(set); of方法,如ImmutableSet.of(“a”, “b”, “c”)或 ImmutableMap.of(“a”, 1, “b”, 2); Builder工具,如

  copyOf 是很智能和高效的,在特定会避免线性拷贝。下期有机会来分析下它的实现原理。 关联可变集合和不可变集合 可变集合接口 属于JDK还是Guava 不可变版本 Collection JDK ImmutableCollection List JDK ImmutableList Set JDK ImmutableSet SortedSet/NavigableSet JDK ImmutableSortedSet Map JDK ImmutableMap SortedMap JDK ImmutableSortedMap Multiset Guava ImmutableMultiset SortedMultiset Guava ImmutableSortedMultiset Multimap Guava ImmutableMultimap ListMultimap Guava ImmutableListMultimap SetMultimap Guava ImmutableSetMultimap BiMap Guava ImmutableBiMap ClassToInstanceMap Guava ImmutableClassToInstanceMap Table Guava ImmutableTable   2. Multiset 定义摘自维基百科: ”集合[set]概念的延伸,它的元素可以重复出现…与集合[set]相同而与元组[tuple]相反的是,Multiset元素的顺序是无关紧要的:Multiset {a, a, b}和{a, b, a}是相等的” Multiset继承自JDK中的Collection接口,而不是Set接口,所以可以包含重复元素。可以从以下角度理解: 没有元素顺序限制的ArrayList Map<E, Integer>,键为元素,值为计数 Multiset提供像无序的ArrayList的基本操作: add(E)添加单个给定元素 iterator()返回一个迭代器,包含Multiset的所有元素(包括重复的元素) size()返回所有元素的总个数(包括重复的元素) 当把Multiset看作Map<E, Integer>时,它也提供了Map的查询操作: count(Object)返回给定元素的计数。 entrySet()返回Set<Multiset.Entry>,和Map的entrySet类似。 elementSet()返回所有不重复元素的Set,和Map的keySet()类似。 常用方法如下: 方法 描述 count(E) 给定元素在Multiset中的计数 elementSet() Multiset中不重复元素的集合,类型为Set entrySet() 和Map的entrySet类似,返回Set<Multiset.Entry>, 其中包含的Entry支持getElement()和getCount()方法 add(E, int) 增加给定元素在Multiset中的计数 remove(E, int) 减少给定元素在Multiset中的计数 setCount(E, int) 设置给定元素在Multiset中的计数,不可以为负数 size() 返回集合元素的总个数(包括重复的元素)   应用:统计一个词在文档中出现了多少次。 传统的做法是这样的

  使用Multiset操作:

  3. Multimap 通俗来讲,Multimap 是一键对多值的HashMap,类似于 Map<K, List> 的数据结构。

  输出:

  常用操作如下: 方法签名 描述 等价于 put(K, V) 添加键到单个值的映射 multimap.get(key).add(value) putAll(K, Iterable) 依次添加键到多个值的映射 Iterables.addAll(multimap.get(key), values) remove(K, V) 移除键到值的映射;如果有这样的键值并成功移除,返回true。 multimap.get(key).remove(value) removeAll(K) 清除键对应的所有值,返回的集合包含所有之前映射到K的值,但修改这个集合就不会影响Multimap了。 multimap.get(key).clear() replaceValues(K, Iterable) 清除键对应的所有值,并重新把key关联到Iterable中的每个元素。返回的集合包含所有之前映射到K的值。 multimap.get(key).clear(); Iterables.addAll(multimap.get(key), values)   主要操作: asMap:为Multimap<K, V>提供Map<K,Collection>形式的视图 entries:返回所有”键-单个值映射”,包括重复键。Collection<Map.Entry<K, V>>类型 keySet:返回所有不同的键,Set类型 keys:用Multiset表示Multimap中的所有键,每个键重复出现的次数等于它映射的值的个数。可以从这个Multiset中移除元素,但不能做添加操作;移除操作会反映到底层的Multimap values:用一个”扁平”的Collection包含Multimap中的所有值,包括重复键   4. BiMap 一般的Map只提供”键-值“的映射,而BiMap则同时提供了”键-值“和”值-键“的映射关系。常用方法: put(K key, V value):添加新的键、值。如果值和已有键重复,会抛出异常 forcePut(K key, V value):添加新的键、值。如果值和已有键重复,会覆盖原来的键、值 inverse():得到”值-键“的BitMap对象

  输出:

  5. Table Table类似多个索引的表,类似 Map<R, Map<C, V>> 的数据结构。它有两个支持所有类型的键:”行”和”列”,可以通过以下方法获取多个视图: rowMap():用Map<R, Map<C, V>>表现Table<R, C, V>。同样的, rowKeySet()返回”行”的集合Set。 row(r):用Map<C, V>返回给定”行”的所有列,对这个map进行的写操作也将写入Table中。 cellSet():用元素类型为Table.Cell的Set表现Table<R, C, V>。Cell类似于Map.Entry,但它是用行和列两个键区分的。   作者: MoonGeek 出处:https://www.cnblogs.com/moongeek/p/12831296.html 版权:本文采用「署名-非商业性使用-相同方式共享 4.0 国际」知识共享许可协议进行许可。

想学Google Guava看这篇就够了

Guava是谷歌提供的一个核心Java类库,其中包括新的集合类型、不可变集合、图库,以及用于并发、I/O、Hash、缓存、字符串等的 实用工具。它在谷歌中的大多数Java项目中被广泛使用,也被许多其他公司广泛使用,熟练掌握这些工具类能帮助我们快速的处理日常开发中的一些问题,比如,不可变集合、集合的转换、字符串处理、本地缓存等 最近一段时间,我把Guava中常用到的工具类学了一遍,感觉有些工具类还是挺有用的,至少它帮你封装了很多功能,让你在处理一些逻辑的时候,不用太关注细节,把Guava的工具类直接拿来用就好了。下面我就介绍一下Guava中最常用的一些工具: 1、Guava不可变集合 不可变集合就是集合创建之后元素是不可改变的,主要用途如下: 不可变对象提供给别人使用时是安全的,因为不可变,所有人都无法进行修改,只能读 支持多个线程调用,不存在竞争的问题,天然支持多线程 不可变集合节省内存空间,因为不可变,集合空间在创建时就已经确定好了,不用考虑扩容等问题,内存利用率高 不可变集合可用于常量 Guava针对常用的集合类型List、Set、Map等都提供了不可变类型的集合 详细使用方法,可查看另一篇博客《Guava系列之不可变集合》 2、Guava新的集合类型 Guava提供了几种新的集合类型,补充了JDK中的集合类型 比如我们要统计List中某个元素出现的次数,如果使用JDK中的list就需要使用循环遍历进行统计,但使用了Guava的Multiset就可以直接统计出来元素出现的次数 再比如,我们要通过Map中的key查找value,通过value来查找值,也就是需要一个双向Map,如果使用JDK中的Map,我们需要维护两个Map,一个从key映射到value,另外一个从value映射到key,而且不管是新增还是修改Map中的元素,都要保持两个Map同步修改,维护成本太高了,使用Guava的BiMap可以通过一个Map轻松解决这个问题 更多新集合类型请查看《Guava系列之新的集合类型》 3、Guava超实用的集合工具类 JDK中集合的操作已经提供了很多工具类,比如基本的集合交集、并集、差集这些常用的操作,Guava中提供的工具类是对JDK的补充,在Guava中提供了静态的创建集合的方法,还有集合的很多操作,比如笛卡尔集、list反转、排列组合、Set转Map、Map的各种过滤等 新集合工具类的详细使用,请查看《Guava系列之超实用的集合工具类》 4、Guava本地缓存Cache Guava中的缓存是本地缓存的实现,与ConcurrentMap相似,但不完全一样。最基本的区别就是,ConcurrentMap会一直保存添加进去的元素,除非你主动remove掉。而Guava Cache为了限制内存的使用,通常都会设置自动回收 Guava Cache的使用场景: 以空间换取时间,就是你愿意用内存的消耗来换取读取性能的提升 你已经预测到某些数据会被频繁的查询 缓存中存放的数据不会超过内存空间 Guava Cache的详细使用方法,可查看《Guava系列之Cache》 5、Guava强大的String工具类 String是我们平时开发工作当中使用最频繁的类型, Guava提供了字符串的连接、分隔等操作,特别是字符串的匹配,那是相当强大,比如提取出字符串中的字母、数字、特殊字符等,可以从指定字符串中提取、删除、替换等操作 举个例子,提取“er 3j6o 3k ,)$ wt@ wr4576je ow3453535345irjew jwfel ” 字符串的字母,直接可以调用现成的方法 再比如,你需要将上述字符串中的数字全部移除或替换成其他字符,都有现成的方法,使用起来非常方便,只要你使用好了这些工具类, 可以大大提升你对字符串的处理效率 具体详细用法,请查看《Guava系列之强大的String工具类》 6、Guava限流RateLimiter 在互联网高并发场景下,限流是用来保证系统稳定性的一种手段,当系统遭遇瞬时流量激增时,可能会由于系统资源耗尽导致宕机。而限流可以把一小部分流量拒绝掉,保证大部分流量可以正常访问,从而保证系统只接收承受范围以内的请求,多余的请求给拒绝掉 我们常用的限流算法有:漏桶算法、令牌桶算法 Guava中的限流使用的是令牌桶算法,RateLimiter提供了两种限流实现 平滑突发限流(SmoothBursty) 平滑预热限流(SmoothWarmingUp) Guava RateLimiter的详细用法,请查看《Guava系列之限流RateLimiter》 7、Guava发布/订阅EventBus EventBus是Guava中实现的用于发布/订阅模式的事件处理组件,它是设计模式中观察者模式的优雅实现 EventBus是消息总线,它会根据消息的类型发送到指定的消息订阅者,当有消息没有订阅者接收时,会将消息发送给DeadEvent 关于EventBus的详细用法,请查看《Guava系列之EventBus》 以上是对最近学习Guava类库的一个总结,它包括了我们平常开发中最常用的一些组件工具类,熟练掌握这些工具类的使用方法,必然会让你的工作如虎添翼~   from:https://www.pianshen.com/article/57281487560/

Google guava工具类的介绍和使用

概述 工具类 就是封装平常用的方法,不需要你重复造轮子,节省开发人员时间,提高工作效率。谷歌作为大公司,当然会从日常的工作中提取中很多高效率的方法出来。所以就诞生了guava。 guava的优点: 高效设计良好的API,被Google的开发者设计,实现和使用 遵循高效的java语法实践 使代码更刻度,简洁,简单 节约时间,资源,提高生产力 Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如: 集合 [collections] 缓存 [caching] 原生类型支持 [primitives support] 并发库 [concurrency libraries] 通用注解 [common annotations] 字符串处理 [string processing] I/O 等等。 使用 引入gradle依赖(引入Jar包)

  1.集合的创建

  创建不可变集合 先理解什么是immutable(不可变)对象 在多线程操作下,是线程安全的 所有不可变集合会比可变集合更有效的利用资源 中途不可改变

  这声明了一个不可变的List集合,List中有数据1,2,3,4。类中的 操作集合的方法(譬如add, set, sort, replace等)都被声明过期,并且抛出异常。 而没用guava之前是需要声明并且加各种包裹集合才能实现这个功能

  当我们需要一个map中包含key为String类型,value为List类型的时候,以前我们是这样写的

  而现在

  其他的黑科技集合

  2.将集合转换为特定规则的字符串 以前我们将list转换为特定规则的字符串是这样写的:

  把map集合转换为特定规则的字符串

  3.将String转换为特定的集合

  如果

  guava还可以使用 omitEmptyStrings().trimResults() 去除空串与空格

  将String转换为map

  4.guava还支持多个字符切割,或者特定的正则分隔

  关于字符串的操作 都是在Splitter这个类上进行的

  5. 集合的过滤 我们对于集合的过滤,思路就是迭代,然后再具体对每一个数判断,这样的代码放在程序中,难免会显得很臃肿,虽然功能都有,但是很不好看。 guava写法

  set的交集, 并集, 差集

  map的交集,并集,差集

  6.检查参数

  免去了很多麻烦!并且会使你的代码看上去更好看。而不是代码里面充斥着 !=null, !="" 检查是否为空,不仅仅是字符串类型,其他类型的判断,全部都封装在 Preconditions类里,里面的方法全为静态 其中的一个方法的源码

  方法声明(不包括额外参数) 描述 检查失败时抛出的异常 checkArgument(boolean) 检查boolean是否为true,用来检查传递给方法的参数。 IllegalArgumentException checkNotNull(T) 检查value是否为null,该方法直接返回value,因此可以内嵌使用checkNotNull。 NullPointerException checkState(boolean) 用来检查对象的某些状态。 IllegalStateException checkElementIndex(int index, int size) 检查index作为索引值对某个列表、字符串或数组是否有效。 index > 0 && index < size IndexOutOfBoundsException checkPositionIndexes(int start, int end, int size) 检查[start,end]表示的位置范围对某个列表、字符串或数组是否有效 IndexOutOfBoundsException 7. MoreObjects 这个方法是在Objects过期后官方推荐使用的替代品,该类最大的好处就是不用大量的重写 toString,用一种很优雅的方式实现重写,或者在某个场景定制使用。

  8.强大的Ordering排序器 排序器[Ordering]是Guava流畅风格比较器[Comparator]的实现,它可以用来为构建复杂的比较器,以完成集合排序的功能。

  示例

  9.计算中间代码的运行时间

  TimeUnit 可以指定时间输出精确到多少时间 10.文件操作 以前我们写文件读取的时候要定义缓冲区,各种条件判断,各种 $%#$@# 而现在我们只需要使用好guava的api 就能使代码变得简洁,并且不用担心因为写错逻辑而背锅了

  Files类中还有许多方法可以用,可以多多翻阅 11.guava缓存 guava的缓存设计的比较巧妙,可以很精巧的使用。guava缓存创建分为两种,一种是CacheLoader,另一种则是callback方式 CacheLoader:

  api中已经把apply声明为过期,声明中推荐使用get方法获取值 callback方式:

  以上只是guava使用的一小部分,guava是个大的工具类,第一版guava是2010年发布的,每一版的更新和迭代都是一种创新。 jdk的升级很多都是借鉴guava里面的思想来进行的。 小结 代码可以在 https://github.com/whirlys/elastic-example/tree/master/guava 下载 细节请翻看 guava 文档 https://github.com/google/guava/wiki 参考: Google guava工具类的介绍和使用 Guava工具类学习   from:https://blog.csdn.net/wwwdc1012/article/details/82228458