AC第一天

一.JAVA

1.以下哪些线程是线程安全的?(ADE)

A. Vector
B. HashMap
C. ArrayList
D. StringBuffer
E. Properties

解析: A. Vector是线程安全的动态数组实现,其所有的方法都被synchronized修饰,在多线程环境下可以安全使用,但是性能比ArrayList
B. HashMap不是线程安全的,在多线程环境下可能出现数据不一致,需要线程安全可以使用ConcurrentHashMap或者Collections.synchronizedMap()
C. ArrayList不是线程安全的,多线程环境可能出现并发修改异常
D. StringBuffer是线程安全的可变字符串类,其关键方法都被synchronized修饰,即同步,如果是单线程的话推荐使用StringBuilder
E. Properties继承自HashTable,而HashTable是线程安全的实现,其所有方法都是同步的

2. 关于匿名内部类的特性有哪些?

📌 基本概念

  • 无类名:编译时自动生成名称(外部类$数字.class
  • 单次使用:定义与实例化同时完成,无法复用
  • 语法形式new 父类/接口() { 类体 }

🛠️ 语法结构

1
2
3
4
5
6
7
8
9
10
11
12
// 实现接口
接口类型 变量 = new 接口类型() {
@Override
public void 方法名() {
// 实现代码
}
};

// 继承类
父类类型 变量 = new 父类类型(构造参数) {
// 重写方法或添加新成员
};

🔐 核心特性

  1. 继承/实现规则
    必须选择以下一种形式:
    a. 继承一个具体类
    b. 实现一个接口

❗ 不能同时继承类和实现接口

  1. 构造限制
    a. 不能声明构造方法
    b. 可用实例初始化块替代

  2. 作用域访问

访问目标规则
外部类成员可访问(含private)
局部变量必须为final/等效final
外部类this外部类名.this

注意

常用来事件监听器、线程实现、集合初始化

Java 8+ 可用Lambda替代部分场景(仅限单方法接口)
每个匿名类都会生成独立的.class文件

与Lambda对比

特性匿名内部类Lambda表达式
适用场景任意接口/类仅函数式接口
语法复杂度较高简洁
this指向自身实例外围实例
字节码生成生成新类使用invokedynamic

二. 数组

1. 基本数据类型所占字节数

数据类型字节默认值
byte10
short20
int40
long80
float40.0f
double80.0d
char2‘\u0000’
boolean4(根据编译环境而定)false

这八种基本类型都有对应的包装类,分别为:Byte、Short、Integer、Long、Float、Double、Character、Boolean。

1Byte(字节或B)=8bit(位或b或比特)
1KB(Kilobyte 千字节)=1024Byte
1MB (Megabyte 兆字节 简称“兆”)=1024KB
1GB (Gigabyte 吉字节 又称“千兆”)=1024MB
1TB (Trillionbyte 万亿字节 太字节)=1024GB
1PB(Petabyte 千万亿字节 拍字节)=1024TB
1EB(Exabyte 百亿亿字节 艾字节)=1024PB,
1ZB (Zettabyte 十万亿亿字节 泽字节)= 1024 EB,
1YB (Yottabyte 一亿亿亿字节 尧字节)= 1024 ZB,
1BB (Brontobyte 一千亿亿亿字节)= 1024 YB.

2. 有序表的二分查找

二分查找,也称为折半查找,是一种高效的搜索算法,用于在有序表中查找目标元素。它的基本思想是将查找区间逐渐缩小为一半,通过比较目标元素与中间元素的大小关系,确定目标元素可能存在的区间,然后在该区间内进行进一步的查找,直到找到目标元素或者确定目标元素不存在。

题目:已知一个有序表a(2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26),当二分查找值为15的元素时,若采取向上取整的方式取中间值,查找成功的比较次数为(4次 )

a一共有13个元素,初始索引为a[0],a[12]
            (0+12+1)/2=6, a[6]=14,14<15,更新左边界为a[7]                              第一次 
            (7+12+1)/2=10,a[10]=22,22>15,更新右边界为a[9]                             第二次
            (7+9+1)/2=8,a[8]=18,18>15,更新右边界为a[7]                                第三次
            (7+7+1)/2=7,a[7]=16,16>15,更新右边界为a[6],左边界比右边距大,失败              第四次

代码

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
public class BinarySearch {
public static void main(String[] args) {
int[] arr = new int[]{2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22};
int pro = 15;
int search = search(arr, pro);
System.out.println(search);
}

public static int search(int[] arr, int pro) {
int left = 0;
int right = arr.length - 1;
int count = 0;

while (left <= right) {
int mid = (right - left) / 2 + left;
int num = arr[mid];
if (num == pro){
break;
} else if (num < pro) {
left = mid + 1;
} else {
right = mid - 1;
}
count++;
}
return count;
}
}

3. 哈希列表的链地址法(装填因子)

定义

链地址法,又称分离链接法,是用于从处理散列函数构造冲突的一种办法。设散列函数得到的散列地址域在区间[0,M-1] ,关键字记录总数为N,则把链地址表中每个链表的平均长度定义为装填因子α,即α=N/M。

题目:已知一组关键字为 {21, 32, 43, 57, 61, 74, 85},采用链地址法处理冲突,散列表是一个下标从0开始的长度为12的一维数组,散列函数为 H(key) = key MOD 12,则装填因子 α 是(7/12)。

4. 快速排序

  1. 先从数组中找一个基准数

  2. 让其他比它大的元素移动到数列一边,比他小的元素移动到数列另一边,从而把数组拆解成两个部分。

  3. 再对左右区间重复第二步,直到各区间只有一个数。

题目:对数组a=[6, 2, 9, 4, 1, 7]采用快速排序的方法,以第一个元素为基准,从小到大排序,则第一次得到的划分结果是([4, 2, 1, 6, 9, 7])