0%

JAVA基础复习

Java基础复习

1、== 与equals方法

对于八种基本数据类型来说(byte short int long float double boolean char) == 是比较的值 而八种基本数据类型 是没有equals方法的

对于引用数据类型来说 == 比较的是对象的内存地址 而equals比较的字面值(例:String类型)

2、Synchronized关键字

作用

  • 原子性所谓原子性就是指一个操作或者多个操作,要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。synchronized修饰的类或对象的所有操作都是原子的,因为在执行操作之前必须先获得类或对象的锁,直到执行完才能释放。
  • 可见性:**可见性是指多个线程访问一个资源时,该资源的状态、值信息等对于其他线程都是可见的。 **synchronized和volatile都具有可见性,其中synchronized对一个类或对象加锁时,一个线程如果要访问该类或对象必须先获得它的锁,而这个锁的状态对于其他任何线程都是可见的,并且在释放锁之前会将对变量的修改刷新到共享内存当中,保证资源变量的可见性。
  • 有序性有序性值程序执行的顺序按照代码先后执行。 synchronized和volatile都具有有序性,Java允许编译器和处理器对指令进行重排,但是指令重排并不会影响单线程的顺序,它影响的是多线程并发执行的顺序性。synchronized保证了每个时刻都只有一个线程访问同步代码块,也就确定了线程执行同步代码块是分先后顺序的,保证了有序性。

Synchronized主要有三种用法

  • 修饰实例方法: 作用于当前对象实例加锁,进入同步代码前要获得 当前对象实例的锁
1
2
3
synchronized void method() {
//业务代码
}
  • 修饰静态方法: 也就是给当前类加锁,会作用于类的所有对象实例 ,进入同步代码前要获得 当前 class 的锁。因为静态成员不属于任何一个实例对象,是类成员( static 表明这是该类的一个静态资源,不管 new 了多少个对象,只有一份)。所以,如果一个线程 A 调用一个实例对象的非静态 synchronized 方法,而线程 B 需要调用这个实例对象所属类的静态 synchronized 方法,是允许的,不会发生互斥现象,因为访问静态 synchronized 方法占用的锁是当前类的锁,而访问非静态 synchronized 方法占用的锁是当前实例对象锁
1
2
3
synchronized void staic method() {
//业务代码
}
  • 修饰代码块 :指定加锁对象,对给定对象/类加锁。synchronized(this|object) 表示进入同步代码库前要获得给定对象的锁synchronized(类.class) 表示进入同步代码前要获得 当前 class 的锁
1
2
3
synchronized(this) {
//业务代码
}

3.Java容器

一、Collection

简单来说就是单个集合的元素

分为List、Set、Queue三大类

List有ArrayList(底层由数组组成 查找快 支持随机访问) LinkedList(底层由双向链表组成 修改快 还可以做栈 队列 以及双向队列) 以及Vector(线程安全 但是效率低 很少用)

List

ArrayList

JDK 7 以无参数构造方法创建 ArrayList 时,直接创建了长度是10的Object[]数组elementData 。

JDK 8 以无参数构造方法创建 ArrayList 时,实际上初始化赋值的是一个空数组。当真正对数组进行添加元素操作时,才真正分配容量。即向数组中添加第一个元素时,数组容量扩为 10。

底层为一个Object类型的数组 初始长度为0;若采用了泛型 ArrayList list = new ArrayList<>();

则生成的是String[]类型的数组 初始长度为0

扩容

当初始长度为10已经加入了十个元素之后,我们需要再加一个元素的时候,我们就需要扩容

1
2
3
4
5
6
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}

这段源代码就是ArrayList的add()方法 如果添加的元素已经满了 则调用grow()函数 很明显 这是一个扩容函数

grow函数有两个 一个有参函数 一个无参函数

无参参数会调用有参参数 进行1.5倍的扩容

1
ArrayList list1 = new ArrayList(23);

这表示着生成了一个初始长度为23的ArrayList数组

Vector

和ArrayList数组类似 线程安全 效率低 用的很少

但是我们用的Stack(栈)则是基于Vector设计的

实现栈

Stack继承Vector 是Vector的子类

LinkedList

基于双向链表实现 增删元素效率高 查询效率低

LinkedList可以用作栈 队列 以及双向队列

Set

集合 无序可去重的集合

TreeSet

​ 无序 不可重复 自动排序 相当于存放在TreeMap的Key部分

HashSet

​ 无序 不可重复 支持快速查找 存放在HashMap中相当于key部分

LinkedHashSet

​ 基于双向链表实现,具有HashSet的查找效率

Queue

LinkedList

可以用他来实现双向队列

PriorityQueue

用于堆实现 可以用它实现优先队列

二、Map

映射类型 Key - Value类型结构、

HashMap

比如最为常见的HashMap

JDK 1.7 底层是数组+链表

JDK 1.8 底层是数组+链表+红黑树 加入红黑树的目的是增加HashMap的插入和查询速率

HaashMap通过key进行hashcode与 与运算 得到下标。

HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。

HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。

HashMap 是无序的,即不会记录插入的顺序。

HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Main {
public static void main(String[] args) throws IOException, Exception {
HashMap<String,String> map = new HashMap<>();
map.put("1","one");
map.put("2","two");
map.put("3","three");
map.put("4","four");
System.out.println(map);

HashMap<String, String> Sites = new HashMap<String, String>();
// 添加键值对
Sites.put("one", "Google");
Sites.put("two", "Runoob");
Sites.put("three", "Taobao");
Sites.put("four", "Zhihu");
Sites.put("apple","lll");
System.out.println(Sites);
// key=商品名称,value=价格,这里以这个例子实现按名称排序和按价格排序.
Map store = new HashMap();

store.put("iphone12", 6799);
store.put("iphone12pro", 8499);
store.put("macbookPro", 19499);
store.put("ipadAir", 6999);
store.put("watch6", 3199);

// 直接输出HashMap得到的是一个无序Map(不是Arraylist那种顺序型储存)
System.out.println(store);

// {ipadAir=6999, iphone12pro=8499, macbookPro=19499, watch6=3199, iphone12=6799}
}

}

起初我验证Map的无序的时候 输出的总是有序的 增加了样本之后才变得无序

但是输入 它内部就有机构形成 无论你是输出十遍还是一百遍 他都是输出一样的顺序

这就是HashMap的无序性和有序性

采用拉链法解决哈希冲突

JDK1.7采用头插法,有可能形成回路

JDK1.8以后采用尾插法

HashMap的默认初始容量为16

  • 必须是 2 的次幂,这也是 jdk 官⽅推荐的

  • 这是因为达到散列均匀,为了提⾼ HashMap 集合的存取效率,所必须的

HashMap 默认加载因⼦:0.75

数组容器达到 3/4 时,开始扩容

JDK 8 之后,对 HashMap 底层数据结构(单链表)进⾏了改进

  • 如果单链表元素超过8个,则将单链表转变为红⿊树;

  • 如果红⿊树节点数量⼩于6时,会将红⿊树重新变为单链表。

hashcode() :通过调用Hashcode()方法得到key的哈希值

通过哈希函数/哈希算法 转换成数组的下表

重写Hashcode()和equals()的原因是

需要达到散列分布均匀

4.JVM,JRE,JDK的区别

总的来说 JVM包括JRE JRE包括JVM

Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。