java常用知识点整理

目录

java知识点整理

java集合底层原理与使用场景

 微服务选型:Dubbo 和Spring Cloud 

BigDecimal:金额相关

mysql使用group by报错

设置springboot超时时间

mysql连接过多Too many connections

常见io报错信息FileNotFoundException

Math常用方法


java知识点整理

java集合底层原理与使用场景

Java提供的众多集合类由两大接口衍生而来:Collection接口和Map接口

Collection接口,常用方法

size()                        // 集合内的对象数量
add(E)/addAll(Collection)     // 向集合内添加单个entity|批量对象
remove(Object)/removeAll(Collection)     // 从集合内删除单个/批量对象
contains(Object)/containsAll(Collection) // 判断集合中是否存在某个/某些对象
toArray()     // 返回包含集合内所有对象的数组

Map接口,k v,常用方法

size()                 // 集合内的对象数量
put(K,V)/putAll(Map)   // 向Map内添加单个/批量对象
get(K)                 // 返回Key对应的对象
remove(K)              // 删除Key对应的对象
keySet()               // 返回包含Map中所有key的Set
values()               // 返回包含Map中所有value的Collection
entrySet()             // 返回包含Map中所有key-value对的EntrySet
containsKey(K)/containsValue(V) // 判断Map中是否存在指定key/value

衍生常用集合类

       List接口继承自Collection,定义以列表形式存储的集合,可以通过index定位到指定位置的对象

get(int)     //返回指定index位置上的对象
add(E)/add(int, E)  // 在List末尾/指定index位置上插入一个对象
set(int, E)         // 替换置于List指定index位置上的对象
indexOf(Object)     // 返回指定对象在List中的index位置
subList(int,int)    // 返回指定起始index到终止index的子List对象


List接口的实现类:

    ArrayList:可变长的对象数组,线程不安全
        特点:查询快,可以直接根据索引定位目标

    LinkedList:基于链表来实现集合的功能,其实现了静态类Node,集合中的每个对象都由一个Node保存,每
                个Node都拥有到自己的前一个和后一个Node的引用
        特点:增删快,插入效率高,查询不能根据索引定位目标,需要一个一个节点从头遍历,遍历
                LinkedList时应用iterator方式,使用get(int)效率低,遍历效率等同于ArrayList

    Vector:基于数组实现,和ArrayList很像
        特点:线程安全,Vector中的方法基本都是synchronized的,其性能低于ArrayList,可以定义数组
                长度扩容的因子

    CopyOnWriteArrayList:基于数组实现,ArrayList的线程安全版,读效率远高于Vector,类似读写
                分离,适合读多写少的多线程场景,只能保证数据的最终一致性,并不能保证数据的实时
                一致性
        特点:在写操作时会先复制出一个副本,在新副本上执行写操作,然后再修改引用,占用更多的内存
                空间,读性能远高于Vector,并发线程越多优势越明显
             只能保证读线程会读到【已完成】的写结果,无法像Vector一样实现读操作的【等待写操作完
             成后再读最新值】的能力

 微服务选型:Dubbo 和Spring Cloud 

微服务(Microservices)是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力

性能对比:
Dubbo 比 Spring Cloud 性能要高一些,因为 Dubbo 采用单一长连接和 NIO 异步通讯(保持连接/轮询处理),使用自定义报文的 TCP 协议,并且序列化使用定制 Hessian2 框架,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况,但不适用于传输大数据的服务调用。而 Spring Cloud 直接使用 HTTP 协议(但也不是强绑定,也可以使用 RPC 库,或者采用 HTTP 2.0 + 长链接方式(Fegin 可以灵活设置))
Dubbo 概述:
    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。简单的说,Dubbo 就是个服务框架,说白了就是个远程服务调用的分布式框架。

流程详解:
    服务容器负责启动,加载,运行服务提供者(Standalone 容器)。
    服务提供者在启动时,向注册中心注册自己提供的服务(Zookeeper/Redis)。
    服务消费者在启动时,向注册中心订阅自己所需的服务。
    注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
    服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
    服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心(根据数据可以动态调整权重)。

Dubbo 特点:
    远程通讯: 提供对多种基于长连接的 NIO 框架抽象封装(非阻塞 I/O 的通信方式,Mina/Netty/Grizzly),包括多种线程模型,序列化(Hessian2/ProtoBuf),以及“请求-响应”模式的信息交换方式。
    集群容错: 提供基于接口方法的透明远程过程调用(RPC),包括多协议支持(自定义 RPC 协议),以及软负载均衡(Random/RoundRobin),失败容错(Failover/Failback),地址路由,动态配置等集群支持。
    自动发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器


经阿里巴巴开源与维护,
Spring Cloud概述:
    Spring Cloud 基于 Spring Boot,为微服务体系开发中的架构问题,提供了一整套的解决方案——服务注册与发现,服务消费,服务保护与熔断,网关,分布式调用追踪,分布式配置管理等
    Spring Boot 是 Spring 的一套快速配置脚手架,使用默认大于配置的理念,用于快速开发单个微服务

核心功能:
    分布式/版本化配置
    服务注册和发现
    路由
    服务和服务之间的调用
    负载均衡
    断路器
    分布式消息传递

流程:
    请求统一通过 API 网关(Zuul)来访问内部服务。
    网关接收到请求后,从注册中心(Eureka)获取可用服务。
    由 Ribbon 进行均衡负载后,分发到后端具体实例。
    微服务之间通过 Feign 进行通信处理业务。
    Hystrix 负责处理服务超时熔断。
    Turbine 监控服务间的调用和熔断相关指标。

各自优缺点:

Dubbo 优点:

Dubbo 支持 RPC 调用,服务之间的调用性能会很好。
支持多种序列化协议,如 Hessian、HTTP、WebService。
Dobbo Admin后台管理功能强大,提供了路由规则、动态配置、访问控制、权重调节、均衡负载等功能。
在国内影响力比较大,中文社区文档较为全面。
阿里重启维护

一些问题:
Registry 严重依赖第三方组件(zookeeper 或者 redis),当这些组件出现问题时,服务调用很快就会中断。
Dubbo 只支持 RPC 调用。使得服务提供方(抽象接口)与调用方在代码上产生了强依赖,服务提供者需要不断将包含抽象接口的 jar 包打包出来供消费者使用。一旦打包出现问题,就会导致服务调用出错,并且以后发布部署会成很大问题(太强的依赖关系)。
另外,以后要兼容 .NET Core 服务,Dubbo RPC 本身不支持跨语言(可以用跨语言 RPC 框架解决,比如 Thrift、gRPC(重复封装了),或者自己再包一层 REST 服务,提供跨平台的服务调用实现,但相对麻烦很多)
Dubbo 只是实现了服务治理,其他微服务框架并未包含,如果需要使用,需要结合第三方框架实现(比如分布式配置用淘宝的 Diamond、服务跟踪用京东的 Hydra,但使用相对麻烦些),开发成本较高,且风险较大。
社区更新不及时(虽然最近在疯狂更新),但也难免阿里以后又不更新了,就尴尬了。
主要是国内公司使用,但阿里内部使用 HSF,相对于 Spring Cloud,企业应用会差一些

Spring Cloud 优点:

有强大的 Spring 社区、Netflix 等公司支持,并且开源社区贡献非常活跃。
标准化的将微服务的成熟产品和框架结合一起,Spring Cloud 提供整套的微服务解决方案,开发成本较低,且风险较小。
基于 Spring Boot,具有简单配置、快速开发、轻松部署、方便测试的特点。
支持 REST 服务调用,相比于 RPC,更加轻量化和灵活(服务之间只依赖一纸契约,不存在代码级别的强依赖),有利于跨语言服务的实现,以及服务的发布部署。另外,结合 Swagger,也使得服务的文档一体化。
提供了 Docker 及 Kubernetes 微服务编排支持。
国内外企业应用非常多,经受了大公司的应用考验(比如 Netfilx 公司),以及强大的开源社区支持

一些问题:
支持 REST 服务调用,可能因为接口定义过轻,导致定义文档与实际实现不一致导致服务集成时的问题(可以使用统一文档和版本管理解决,比如 Swagger)。
另外,REST 服务调用性能会比 RPC 低一些(但也不是强绑定)
Spring Cloud 整合了大量组件,相关文档比较复杂,需要针对性的进行阅读

使用 Dubbo 构建的微服务架构就像组装电脑,各环节我们的选择自由度很高,但是最终结果很有可能因为一条内存质量不行就点不亮了,总是让人不怎么放心,但是如果你是一名高手,那这些都不是问题;而 Spring Cloud 就像品牌机,在 Spring Source 的整合下,做了大量的兼容性测试,保证了机器拥有更高的稳定性,但是如果要在使用非原装组件外的东西,就需要对其基础有足够的了解

 

Spring Cloud 核心组件:
Eureka:各个服务启动时,Eureka Client 都会将服务注册到 Eureka Server,并且 Eureka Client 还可以反过来从 Eureka Server 拉取注册表,从而知道其他服务在哪里。
Ribbon:服务间发起请求的时候,基于 Ribbon 做负载均衡,从一个服务的多台机器中选择一台。
Feign:基于 Feign 的动态代理机制,根据注解和选择的机器,拼接请求 URL 地址,发起请求。
Hystrix:发起请求是通过 Hystrix 的线程池来走的,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题。
Zuul:如果前端、移动端要调用后端系统,统一从 Zuul 网关进入,由 Zuul 网关转发请求给对应的服务。

BigDecimal:金额相关

BigDecimal 是java小数操作的一个专有类,在电商、金融行业 存储跟金额有关的字段

Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算,双精度浮点型变量double可以处理16位有效数。不论是float 还是double都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度,在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象

     BigDecimal a = new BigDecimal(5);
     BigDecimal b = new BigDecimal(40);
     BigDecimal add = a.add(b); // +
     BigDecimal subtract = a.subtract(b); // -
     BigDecimal multiply = a.multiply(b); // *

     BigDecimal divide = a.divide(b); // \
     BigDecimal result5 = num2.divide(num1, 20, BigDecimal.ROUND_HALF_UP)//后面说明
     第二个参数为保留几位小数,➗务必写成这种,防止异常java.lang.ArithmeticException

     BigDecimal result4 = num3.abs(); //绝对值
        
注意:  System.out.println()中的数字默认是double类型的,double类型小数计算不精准。
        使用BigDecimal类构造方法传入double类型时,计算的结果也是不精确的!


取整:
BigDecimal bd = new BigDecimal("12.1");
long l  = bd.setScale( 0, BigDecimal.ROUND_UP ).longValue(); // 向上取整
long l  = bd.setScale( 0, BigDecimal.ROUND_DOWN ).longValue(); // 向下取整

BigDecimal b = new BigDecimal("2.225667").setScale(2, BigDecimal.ROUND_DOWN);
//b = 2.22 直接去掉多余的位数

BigDecimal c = new BigDecimal("2.224667").setScale(2, BigDecimal.ROUND_UP);
//c = 2.23 跟上面相反,进位处理

因为不是所有的浮点数都能够被精确的表示成一个double 类型值,有些浮点数值不能够被精确的表示成 double 类型值,因此它会被表示成与它最接近的 double 类型的值。必须改用传入String的构造方法。这一点在BigDecimal类的构造方法注释中有说明

//尽量用字符串的形式初始化
    BigDecimal num12 = new BigDecimal("0.005");
    BigDecimal num12 = new BigDecimal(Double.toString(d));
    BigDecimal num12 = BigDecimal.valueOf(1.010);
    // 使用string类型额构造函数进行构造时,equals无法比较,比如多余的0
    // compareTo方法则只会进行大小的比较,与精度无关:1.010=1.01为true

  • 返回为正数表示a1>a2, 返回为负数表示a1
  • System.out.println(String.valueOf(4).compareTo(String.valueOf(5)));//-1

    //        c=1.010 ,b=1.01, c.compareTo(b) = 0  //b c 都是BigDecimal类型
    // 使用valueof方法进行构造时,他会帮我们去掉多余的精度可以用equals比较
    //        c.equals(b)  = true

BigDecimal 精度描述:

模式               描述
CEILING        正无穷大方向取整
FLOOR          负无穷大方向取整
DOWN           向 0 的方向取整
UP                 正数向正无穷大取整,负数向负无穷大取整
HALF_UP          5,6,7,8,9 向上取整、 1,2,3,4 向下取整、 常用的4舍5入
HALF_DOWN    6,7,8,9 向上取整 1,2,3,4,5 向下取整
HALF_EVEN     小数位是5时,判断整数部分是奇数就进位、 小数位是5时,判断整数部分是偶数就舍弃、
                           1,2,3,4, 舍弃、 6,7,8,9, 进位


常用方法PS
currency = NumberFormat.getCurrencyInstance();    //建立货币格式化引用
NumberFormat percent = NumberFormat.getPercentInstance();     //建立百分比格式化用
percent.setMaximumFractionDigits(3);               //百分比小数点最多3位

currency.format(bigLoanAmount)
percent.format(bigInterestRate)
currency.format(bigInterest)

BigDecimal数字数据转String文本

直接返回给前端的话11.00会显示为11,

// 浮点数的打印
System.out.println(new BigDecimal("10000000000").toString());

// 普通的数字字符串
System.out.println(new BigDecimal("100.000").toString());

// 去除末尾多余的0
System.out.println(new BigDecimal("100.000").stripTrailingZeros().toString());

// 避免输出科学计数法
System.out.println(new BigDecimal("100.000").toPlainString());

// 四舍五入,保留两位小数,避免输出科学计数法
System.out.println(new BigDecimal("100.000").setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());

 

mysql使用group by报错

错误信息:incompatible with sql_mode=only_full_group_by

解决办法:

  • 一般网上各种关于这个问题的帖子,基本都会提到 my-default.cnf 这个文件,这是通过 Homebrew 安装 MySQL 后会在指定目录下生成的默认文件
  • 如果能在 /usr/local/opt/mysql/support-files/ 目录下找到该文件
  • 则直接运行 cp /usr/local/opt/mysql/support-files/my-default.cnf /etc/my.cnf 将该文件复制到 /etc/ 目录下,并重命名为 my.cnf
  • 输入 vi /etc/my.cnf ,在文件最末尾添加如下脚本
  • 注意该脚本等号后面的部分没有被单引号爆过,而且末尾没有分号
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
  • brew services stop mysql
  • brew services start mysql     重启数据库

方法2:

  • 在终端输入 sudo /usr/libexec/locate.updatedb
  • 会需要等待一段时间,命令会自动执行完成
  • 之后输入 locate my.cnf ,就会在命令下方输出初始化的 my.cnf 所在目录,如下图
  • 输入 vi /usr/local/etc/my.cnf ,在文件末尾添加上一个解决方法相同的脚本
  • 退出保存后重启数据库即可
     

设置springboot超时时间

spring.mvc.async.request-timeout=20000

spring:
  datasource:
    remove-abandoned-timeout: 20000

mysql连接过多Too many connections

  • mysql -u root -p 回车输入密码进入mysql
  • show processlist;  查看连接数,处于sleep状态的,是暂时没有用的,所以可以kill掉
  • show variables like "max_connections"; 查看最大连接数
  • set GLOBAL max_connections=1000;  修改最大连接数
  • show global variables like 'wait_timeout';mysql在关闭一个非交互的连接之前要等待的秒数,默认是28800s
  • set global wait_timeout=300;  修改这个数值,最好控制在几分钟内
  • set global interactive_timeout=500;  修改这个数值,表示mysql在关闭一个连接之前要等待的秒数,可以让mysql自动关闭那些没用的连接,但要注意的是,正在使用的连接到了时间也会被关闭,因此这个时间值要合适

常见io报错信息FileNotFoundException

java.io.FileNotFoundException: .\xxx\xxx.txt (系统找不到指定的路径。)

//原因:当前所指定的文件不存在或者目录不存在

文件不存在则创建
if(!file.exists()){
    //先得到文件的上级目录,并创建上级目录,在创建文件
    file.getParentFile().mkdir();
    try {
        //创建文件
        file.createNewFile();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

java.io.FileNotFoundException: .\xx\xx (拒绝访问。)

//原因:你访问了一个文件目录,而不是文件

读写文件路径要写成: "G:/data/image/test.png";
不能写成:"G:/data/image/";

Math常用方法

int value = Math.abs(-90); // 取绝对值
Math.pow(a, b)    // 计算a的b次方
Math.max(2.3,4.5); // 计算最大值 4.5
Math.min(2.3,4.5); // 计算最小值 2.3
Math.ceil(-10.1);  // ceil天花板的意思,就是返回大的值 -10.0 ,10.7--11.0 
Math.floor(-10.1);  // floor地板的意思,就是返回小的值 -11.0, 10.7--10.0
Math.random() // 小于1大于0的double类型的随机数 
Math.rint(10.1) // rint 四舍五入,返回double值 ,.5的时候会取偶数,10.5--10
Math.round(10.1) // round 四舍五入,float时返回int值,double时返回long值,10.5--11

 

 

未完

 

你可能感兴趣的:(java,学习与记录,java)