java总结

目录

  • 1.java基础
    • 1.1 JDK和JRE的区别
    • 1.2 ==和equals的区别
    • 1.3 hashCode() 和 equals()
    • 1.4 final 在 java 中的作用
    • 1.5 java基本数据类型
    • 1.6 jdk1.8 List stream用法
    • 1.7 java Math.round方法
    • 1.8 String、StringBuffer、StringBuilder
    • 1.9 抽象类
    • 1.10 抽象接口
    • 1.11 IO流
  • 2.容器
  • 3.标题多线程
  • 4.标题设计模式
  • 5.Spring / Spring MVC
  • 6.Spring Boot
  • 7.Spring cloud
  • 8.Doubble
  • 9.负载均衡
  • 10.数据库
  • 11.缓存

1.java基础

1.1 JDK和JRE的区别

1、JDK :Java Development Kit(java开发工具包)。即java语言编写的程序所需要的开发工具包,  	
  JDK包含了JRE,同时还包括java	源码编译器javac、监控工具jconsole、分析工具jvisualvm等

2、JRE :Java Runtime Environment(java运行时环境)。即java运行时的环境包,含了java虚拟机,  
  java基础类库 

1.2 ==和equals的区别

1、==作用:
基本类型,比较值是否相等
引用类型,比较内存地址是否相等

2、equals方法的作用
比较的是值是否相等

3、== 是关系运算符,equals是方法。结果都返回布尔类型。

// Demo如下
public static void main(String[] args) {
     
    String a = "hello";
    String b = "hello";
    String c = new String("hello");
    System.out.println(a == b); // 1 true
    System.out.println(a == c); // 2 false
    System.out.println(a.equals(b)); // 3 true
    System.out.println(a.equals(c)); // 4 true
    
    String d = "123";
    Integer e = 123;
    System.out.println(d.equals(e)); // 5 false
        
    Cat c1 = new Cat("张三");
    Cat c2 = new Cat("张三");
    System.out.println(c1.equals(c2)); // 6 false
}

static class Cat {
     

    private String name;

    public Cat(String name) {
     
        this.name = name;
    }
}
== 结果
1.true
2.false
3.true
4.true

5.false

6.false
1中  a == b 结果为true。 因为字符串在java中是特殊的,直接使用=指向的是常量池中的变量。
当第一次a="hello"时常量池中没有"hello"会新创建"hello",当b="hello"时 因为a已经在常量池创建了"hello"
所以b直接指向常量池。所以a和b的引用是指向同一个块内存 所有a==b是true。

2中  a==c 结果为false。注意c=new String("hello"); 使用new关键字创建一个字符串。
new会直接在内存中开辟一块新的内存存放"hello",而不会从常量池中获取"hello"。
所以a和c的引用指向不同 a==c结果为false.

3、4 中 equals比较的是值,所以a.equals(b)和a.equals(c)结果为true

5中  结果为false ,为什么equals结果为fasle? 可以看下面的疑问,会根据源码进行解释

6中  结果是false equals比较结果为什么还是false。这个要看Object源码。可以看下面的疑问,会根据源码进行解释

疑问:

  1. 5中 结果为什么为false?
    看一下String equals方法 源码第8行 if (anObject instanceof String) ,发现会进行数据类型验证。如果数据类型不一致结果我false。因为5中一个是字符串类型一个是数字类型 类型不一致所以为false
  2. 6中 equals比较结果为什么是false?
    通过看Object equals方法 源码。发现Object的equals方法使用的是== ,也就是比较的是内存地址,而Cat 没有重写Object的equals方法,所以调用的是Object的equals方法,因为对象都是new的所以内存地址不一致
  3. 为什么3、4 中的equals 结果为true?
    通过看String 源码发现 String 重写了 equals方法。重写的equals方法比较的是值而不是内存地址
// Object equals 源码
public boolean equals(Object obj) {
     
    return (this == obj);
}
// String equals 源码
public boolean equals(Object anObject) {
     
   if (this == anObject) {
     
      // 先验证内存地址是否相同,内存地址相同值肯定相等
       return true;
   }
   // 验证anObject是否是字符串类型 如果不是则直接返回false
   if (anObject instanceof String) {
     
       String anotherString = (String)anObject;
       int n = value.length;
       // 验证值的长度是否一样 如果不一样肯定不相等直接返回false
       if (n == anotherString.value.length) {
     
           char v1[] = value;
           char v2[] = anotherString.value;
           int i = 0;
           while (n-- != 0) {
     
               if (v1[i] != v2[i])
                   return false;
               i++;
           }
           return true;
       }
   }
   return false;
}

总结:

  1. 比较值是否相等建议用equals()比较
  2. 不同数据类型的数据不能用equals()比较是否相等
  3. 如果对象没有重写Object的equals()方法 那么会调用Object的equals()。而Object中的equals()方法用的是== 比较的是内存地址容易出现问题。所以要比较值是否相等最好重写equals()方法

1.3 hashCode() 和 equals()

hashCode是一个hash算法,可能出现相同的hashCode散列码

看下面的Demo如下:

public static void main(String[] args) {
     
    String a = "方面";
    String b = "树人";
    System.out.println("a hashCode=" + a.hashCode());
    System.out.println("b hashCode=" + b.hashCode());
    System.out.println(a.equals(b));
}
== 结果
a hashCode=846025
b hashCode=846025
false

总结:

  1. hashCode相同equals不一定相等
  2. equals相等hashCode一定相等
  3. 如果不重写hashCode会根据对象的内存地址计算出一个值
  4. 在重写hashCode的时候要重写equals
  5. 如果对象重写方法时最好hashCode和equals都重写

1.4 final 在 java 中的作用

  1. 修饰类:表示该类不能被继承
  2. 修饰方法:表示方法不能被重写
  3. 修饰变量:表示变量只能一次赋值后不能被修改

当final修饰的是一个基本数据类型时,这个数据的值在初始化后将不能被改变。

当final修饰的是一个引用类型时,引用在初始化后将永远指向一个内存地址不可在修改,但是该内存地址中保存的对象信息内容是可以修改的

1.5 java基本数据类型

分类 名称 基本类型 包装类型 占用存储空间 位数 数据范围 表示类型
整数类型 字节型 byte Byte 1个字节 8位 -128 ~ 127 默认值:(byte)0
短整型 short Short 2个字节 16位 -2^15 ~ 2^15-1 默认值:(short)0
整型 int Integer 4个字节 32位 -2^31 ~ 2^31-1 默认值:0
长整型 long Long 8个字节 64位 -2^63 ~ 2^63-1 默认值:0L ;用l或L表示
浮点类型 单精度型 float Float 4个字节 32位 1 位符号位,8 位指数,23 位有效尾数;
3.402823e+38 ~ 1.401298e-45
(e+38表示是乘以10的38次方,同样,e-45表示乘以10的负45次方)
默认值:0.0F; 用f或F表示
双精度型 double Double 8个字节 64位 1 位符号位,11 位指数,52 位有效尾数;
1.797693e+308~ 4.9000000e-324
默认值:0.0D; 用d或D表示
字符类型 字符型 char Character 2个字节 16位 字符的存储范围在\u0000~\uFFFF 默认值:'/uoooo'(null);java字符使用Unicode编码
布尔类型 布尔型 boolean Boolean 1个字节 0或1 true或false 默认值:false

1.6 jdk1.8 List stream用法

list.stream() 和 list.parallelStream()
parallelStream() 是并行流处理。注意并行流是多线程处理如果涉及到线程安全的时候需要注意
默认使用了fork-join框架,其默认线程数是CPU核心数。

  1. List< User> list 转 Map
    第一种:
    Map map = list.stream().collect(Collectors.toMap(User::getId, User -> User));

    第二种
    Map map = list.stream().collect(Collectors.toMap(User::getId, Function.identity()));

  2. List< User> list 转 Map 如果key有重复的用上面两种会报错 用下面两种
    第一种:
    Map map = list.stream().collect(Collectors.toMap(User::getId, User -> User, (oldValue, newValue) -> newValue));

    第二种:
    Map map = list.stream().collect(Collectors.toMap(User::getId, Function.identity(), (oldValue, newValue) -> newValue));

  3. List< User> list 转 Map>
    Map> map = list.stream().collect(Collectors.groupingBy(User::getName));

  4. List< User> list 转 Map>
    Map> map = list.stream().collect(Collectors.groupingBy(User::getName, Collectors.mapping(User::getId, Collectors.toList())));

  5. List< User> list 转 List< Integer>
    List< Integer> ids = list.stream().map(User::getId).collect(Collectors.toList());

  6. List< User> list 转 List< String> 如果有重复的名字去重 distinct()
    List< String> names = list.stream().map(User::getName).distinct().collect(Collectors.toList());

  7. List< User> list 筛选状态为1的用户,其他状态的忽略
    List< User> newList = list.stream().filter(u -> (u.getStatus() == 1)).collect(Collectors.toList());

  8. List< User> list 根据id排序 并取前5条数据 默认正序排列
    List< User> newList = list.stream().sorted(Comparator.comparing(User::getId)).limit(5).collect(Collectors.toList());

  9. List< User> list 根据id排序 并取前5条数据 倒序排列 reversed()
    List< User> newList = list.stream().sorted(Comparator.comparing(User::getId).reversed()).limit(5).collect(Collectors.toList());

  10. List< User> list 根据id排序 如果id为null的在最前面,排序完成后在根据名字排序(如果id相同或id为null时会在根据名称重新排序) nullsFirst-为null的数据在前面,nullsLast-为null的数据在最后面
    List< User> newList = list.sort(Comparator.comparing(User::getId, Comparator.nullsFirst(Integer::compareTo)).thenComparing(User::getName));

1.7 java Math.round方法

pu
blic static void main(String[] args) {
     
    System.out.println(Math.round(-4.4));
    System.out.println(Math.round(-4.5));
    System.out.println(Math.round(-4.6));
    System.out.println(Math.round(4.4));
    System.out.println(Math.round(4.5));
    System.out.println(Math.round(4.6));
}
== 结果
-4
-4
-5
4
5
5

1.8 String、StringBuffer、StringBuilder

String、StringBuffer、StringBuilder都是操作字符串的
String 每次操作都会创建新的对象,然后将指针指向新的 String 对象 比较消耗性能。
StringBuffer、StringBuilder可以在原有对象的基础上进行操作。

StringBuffer、StringBuilder区别
StringBuffer:是线程安全的,每个方法都使用synchronized关键字修饰
StringBuilder:是非线程安全的

1.9 抽象类

关键词:abstract
  1. 可以定义构造方法
  2. 可以有抽象方法和普通方法
    抽象方法不可以同时有static(静态),native(本地),synchronied(同步)方法中的任何一个
  3. 可以是任意权限修饰符
  4. 可以定义成员变量
  5. 可以包含静态方法
  6. 一个类只能继承一个抽象类
  7. 有抽象方法一定是抽象类,抽象类不一定有抽象方法

1.10 抽象接口

  1. 不能定义构造器
  2. 全是抽象方法
  3. 只能用public权限修饰符修饰
  4. 所有成员变量实际上都是常量
  5. 不能有静态方法
  6. 一个类可以实现多个抽象接口

1.11 IO流

篇幅比较长,跳转到IO篇

java IO

2.容器

3.标题多线程

4.标题设计模式

5.Spring / Spring MVC

6.Spring Boot

7.Spring cloud

8.Doubble

9.负载均衡

10.数据库

11.缓存

你可能感兴趣的:(java总结,java面试题,java)