- 下面哪段程序能够正确的实现了GBK编码字节流到UTF-8编码字节流的转换:
byte[] src,dst;
A dst=String.frombytes(src,”GBK”).getbytes(“UTF-8”)
B dst=new String (src,”GBK”).getbytes(“UTF-8”)
C dst=new String (”GBK”, src,) getbytes()
D dst=String.encode(String.decode(src,”GBK”)), “UTF-8”
(1)GBK -> UTF8 转换,前提:byte[] src, dst;
(字节数组先解码得到字符串,再编码得到字节数组):dst = new String(src,“GBK”).getBytes(“UTF-8”)
(2)GBK -> UTF8 转换,前提:String src, dst;
(字符串先编码得到字节数组,再解码得到字符串):dst = new String(src.getBytes(“gbk”), “UTF-8”) - 下列关于java并发的说法中正确的是:(B)
A copyonwritearraylist适用于写多读少的并发场景
B readwritelock适用于读多写少的并发场景
C concurrenthashmap的写操作不需要加锁,读操作需要加锁
D 只要在定义int类型的成员变量i的时候加上volatile关键字,那么多线程并发执行i++这样的操作的时候就是线程安全的了
【知识点】 并发
【分析】
CopyOnWriteArrayList适合使用在读大于写操作的场景里,比如缓存。
ReadWriteLock 当写操作时,其他线程无法读取或写入数据,而当读操作时,其它线程无法写入数据,但却可以读取数据 。适用于读取远远大于写入的操作。
ConcurrentHashMap是一个线程安全的Hash Table,它的主要功能是提供了一组和HashTable功能相同但是线程安全的方法。ConcurrentHashMap可以做到读取数据不加锁,并且其内部的结构可以让其在进行写操作的时候能够将锁的粒度保持地尽量地小,不用对整个ConcurrentHashMap加锁。
【多线程】
并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个 处理机 上运行。其中两种并发关系分别是同步和互斥
互斥:进程间相互排斥的使用临界资源的现象,就叫互斥。
同步: 进程之间的关系不是相互排斥临界资源的关系,而是相互依赖的关系。进一步的说明:就是前一个进程的输出作为后一个进程的输入,当第一个进程没有输出时第二个进程必须等待。具有同步关系的一组并发进程相互发送的信息称为消息或事件。
其中并发又有伪并发和真并发,伪并发是指单核处理器的并发,真并发是指多核处理器的并发。
并行:在单处理器中多道程序设计系统中,进程被交替执行,表现出一种并发的外部特征;在多处理器系统中,进程不仅可以交替执行,而且可以重叠执行。在多处理器上的程序才可实现并行处理。从而可知,并行是针对多处理器而言的。并行是同时发生的多个并发事件,具有并发的含义,但并发不一定并行,也亦是说并发事件之间不一定要同一时刻发生。
多线程:多线程是程序设计的逻辑层概念,它是进程中并发运行的一段代码。多线程可以实现线程间的切换执行。
异步:异步和同步是相对的,同步就是顺序执行,执行完一个再执行下一个,需要等待、协调运行。异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这一事件完成后再工作。线程就是实现异步的一个方式。异步是让调用方法的主线程不需要同步等待另一线程的完成,从而可以让主线程干其它的事情。
异步和多线程并不是一个同等关系,异步是最终目的,多线程只是我们实现异步的一种手段。异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回而可以做其它的事情。实现异步可以采用多线程技术或则交给另外的进程来处理。 - 访问修饰符
- 在Java中,HashMap中是用哪些方法来解决哈希冲突的?
A 开放地址法
B 二次哈希法
C 链地址法
D 建立一个公共溢出区
在Java中,保存数据有两种比较简单的数据结构:数组和链表。数组的特点是:寻址容易,插入和删除困难;链表的特点是:寻址困难,但插入和删除容易;所以我们将数组和链表结合在一起,发挥两者各自的优势,使用一种叫做链地址法的方式可以解决哈希冲突:
- 简单总结一下HashMap是使用了哪些方法来有效解决哈希冲突的:
使用链地址法(使用散列表)来链接拥有相同hash值的数据;
使用2次扰动函数(hash函数)来降低哈希冲突的概率,使得数据分布更平均;
引入红黑树进一步降低遍历的时间复杂度,使得遍历更快; - 开放地址法:寻找下一个为空的数组下标,而后将冲突元素存储
- 再散列法(二次哈希法):再次使用一个不同的哈希算法再计算一次 (第一次%16换另一个数进行%运算)
- 阅读下列程序,选择哪一个是正确的输出结果(C)
class HelloA{
public HelloA()
{
System.out.println("I’m A class ");
}
static
{
System.out.println("static A");
}
}
public class HelloB extends HelloA{
public HelloB()
{
System.out.println("I’m B class");
}
static{
System.out.println("static B");
}
public static void main (String[] args){
new HelloB();
}
}
A static A I’m A class static B I’m B class
B I’m A class I’m B class static A static B
C static A static B I’m A class I’m B class
D I’m A class static A I’m B class static B
【解析】: 类的初始化顺序是: 1、初始化父类中的静态成员变量和静态代码块。 2、初始化子类中的静态成员变量和静态代码块。 3、初始化父类中的普通成员变量和代码块,在执行父类中的构造方法。 4、初始化子类中的普通成员变量和代码块,在执行子类中的构造方法。
- try-catch-finally语句块中含有return 见之前的博客分析
- 以下是java concurrent包下的4个类,选出差别最大的一个(C)
A Semaphore
B ReentrantLock
C Future
D CountDownLatch
【解析】:
A:Semaphore:类,控制某个资源可被同时访问的个数;
B:ReentrantLock:类,具有与使用synchronized方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大;
C:Future:接口,表示异步计算的结果;
D: CountDownLatch: 类,可以用来在一个线程中等待多个线程完成任务的类。 - .关于sleep和wait,以下描述错误的是(D)
A sleep是线程类的方法,wait是object的方法
B sleep不释放对象锁,wait放弃对象锁
C sleep暂停线程,但监控状态依然保持,结束后会自动恢复
D wait进入等待锁定池,只有针对此对象发出notify方法获得对象锁进入运行状态
【解析】:
A:sleep()是Thread类中的方法,而wait()则是Object类中的方法。
sleep()方法导致了程序暂停,但是他的监控状态依然保持着,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放对象锁。 wait()方法导致线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。注意是准备获取对象锁进入运行状态,而不是立即获得。
sleep()和wait()区别 见博客: - 下列代码的输出结果是()
boolean b=true?false:true==true?false:true;
System.out.println(b);
A true
B false
C null
D 空字符串
回答: A (错误)
正确答案: B
【解析】:==优先级大于?:
?:计算方向:从右到左
执行顺序如图:
- 【把字符串转换为整数】
将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
输入描述:
输入一个字符串,包括数字字母符号,可以为空
返回值描述:
如果是合法的数值表达则返回该数字,否则返回0
【思路】:可以先将字符串转为字符数组,然后注意判断首位,首位判断是+还是-号后记得处理正负号,把它转化为字符0(‘0’)
本题关键:1.空字符串处理
2.正负号处理;
3.字符串中非法字符的处理
public static int StrToInt(String str) {
if(str == null || str.isEmpty()){
return 0;
}
int n=1;
int num =0;
char[] s = str.toCharArray();
if (s[0] == '+'){//处理正号
n=1;
s[0]='0';//注意是‘0’
}else if (s[0] == '-'){
n=-1;
s[0] ='0';
}
for (int i = 0; i < s.length; i++) {
if (s[i] <'0'|| s[i] >'9'){
num =0;
break;
}
num = num*10+s[i]-'0';//s[i]-'0' 按ASCII表上相减,结果是数字
}
return num*n;
}
9.【不要二】
二货小易有一个W*H的网格盒子,网格的行编号为0W-1,网格的列编号为0H-1。每个格子至多可以放一块蛋糕,任意两块蛋糕的欧几里得距离不能等于2。
对于两个格子坐标(x1,y1),(x2,y2)的欧几里得距离为:
( (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2) ) 的算术平方根。小易想知道最多可以放多少块蛋糕在网格盒子里。
输入描述:
每组数组包含网格长宽W,H,用空格分割.(1 ≤ W、H ≤ 1000)
输出描述:
输出一个最多可以放的蛋糕数
【解析】:
如果(x1,y1)放了蛋糕,则满足 ( (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2) ) == 4的(x2,y2)不能放蛋糕。
( (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2) ) == 4看起来是一个无解的表达式。
但是可以用加法表达式分解:1+3=4;3+1=4;2+2=4;0+4=4;4+0=4;
仔细分析前三个表达式是不可能的,因为(x1-x2) * (x1-x2)表达式结果不能等于2或3。也就是说( (x1-x2) * (x1-x2) 和(y1-y2) * (y1-y2) )两个表达式一个等于0,一个等于4。
可以看出:假设放蛋糕的位置是(x1,y1),则不能放蛋糕的位置(x2,y2),满足x1=x2,y1-y2=2或者x1-x2=2,y1=y2。即在arr[i][j]处放了蛋糕后,arr[i+2][j]和arr[i][j+2]处就不能放蛋糕了
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int col = scan.nextInt();//列 h 长
int row = scan.nextInt();//行 w 宽
int[][] arr = new int[row][col];
int count = 0;
for(int i =0;i<row;i++){
for(int j=0;j<col;j++){
if(arr[i][j] == 0){
count++;
if(i+2< row){
arr[i+2][j] = 1;
}
if(j+2< col){
arr[i][j+2] = 1;
}
}
}
}
System.out.println(count);
}