算术问题,方法的解:
== 与 equals
==是一个比较运算符,基本数据类型比较的是值,引用数据类型比较的是地址值。
equals()是一个方法,只能比较引用数据类型。重写前比较的是地址值,重写后比较的对象属性。
public static void main(String[]args){ Integer a=new Integer(100); Integer b=new Integer(100); int i=100; Integer j=100; System.out.println("a == b: "+(a==b) ); //false System.out.println("i == j: "+(i==j)); //true System.out.println("i ==a :"+(a.equals(i))); //true System.out.println("b == j"+(b.equals(j))); //true }
Integer的equals源码
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
{ String s=new String("11"); String s1=new String("11"); String s2="11"; System.out.println("s == s1 :" +(s==s1)); //false System.out.println("s ==s1 :"+(s.equals(s1))); //true System.out.println("s ==s2 :"+(s==s2)); //false System.out.println("s ==s2 :"+(s.equals(s2))); //true }
String源码
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String aString = (String)anObject;
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
}
return false;
}
Object对象的 hashCode equals方法的区别:
Java判重需要依次运行以上两个方法,为什么呢?首先hashCode方法会对对象生成一个hash值,效率非常高,但是并完全不可靠。有以下的推断
1.equal()相等的两个对象他们的hashCode()肯定相等,也就是用equal()对比是绝对可靠的。
2.hashCode()相等的两个对象他们的equal()不一定相等,也就是hashCode()不是绝对可靠的。
所以解决方式是:每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equal()去再对比了),如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!
hashset 简单实现原理
HashSet它不保证存储元素的迭代顺序;此类允许使用null元素。
HashSet中不允许有重复元素,这是因为HashSet是基于HashMap实现的,HashSet中的元素都存放在HashMap的key上面,而value中的值都是统一的一个固定对象private static final Object PRESENT = new Object();
HashSet中add方法调用的是底层HashMap中的put()方法,而如果是在HashMap中调用put,首先会判断key是否存在,如果key存在则修改value值,如果key不存在这插入这个key-value。而在set中,因为value值没有用,也就不存在修改value值的说法,因此往HashSet中添加元素,首先判断元素(也就是key)是否存在,如果不存在这插入,如果存在着不插入,这样HashSet中就不存在重复值。
所以判断key是否存在就要重写元素的类的equals()和hashCode()方法,当向Set中添加对象时,首先调用此对象所在类的hashCode()方法,计算次对象的哈希值,此哈希值决定了此对象在Set中存放的位置;若此位置没有被存储对象则直接存储,若已有对象则通过对象所在类的equals()比较两个对象是否相同,相同则不能被添加。
ConcurrentHashMap问题?
1.7 是靠采用Segment数组
+ HashEntry数组实现,每段Segment都有不同的锁,使用Reentranlock加锁;1.8 是采用
Node数组
+ CAS
+ Synchronized
来保证并发安全进行实现。
Segment数组默认的大小是16,Node数组也是16。
get 方法实现,value声明为volatile,保证了修改的可见性,因此不需要加锁
put 方法:
size:1.7 首先采用不加锁的方式计算两次,如果两次结果相同则返回,若不一致,则锁住所有的Segment求和 1.8 中使用一个volatile
类型的变量baseCount
记录元素的个数,当插入新数据或则删除数据时,会通过addCount()
方法更新baseCount
resize 1.7 跟hashmap一样,但是在单线程中扩容 1.8 支持并发扩容,HashMap扩容在1.8中由头插改为尾插(为了避免死循环问题)
序列化问题:收藏
线程问题:
线程复用是调用run方法,是线程池底层的Worker不断运行run方法,从队列里得到Task对象,运行Run方法。
造成线程停止运行的情况:抛出一个异常 ; 调用sleep方法,线程是暂停运行,创建一个新线程和优先级更高的线程进入就绪状态,是抢占,不是终止。
线程运行start方法成为就绪态
Java类型转换:
short s=23;
s+=12;
float f=23+23.23; // 错误,类型转换double - >float
short s1=23;
s1=s1+23; // 错误,int - > short
byte a=0,b=3;
byte c= (a+b); // int - > byte ,
RandonAccessFile 的方法区别 seek 绝对定位,能定位到文件的具体位置,消耗大; skipBytes ,相对定位,能跳过相对的字节数。
内部类:
划分:静态内部类,成员内部类,局部内部类,匿名内部类。
引用成员内部类OuterClass.this new InnerClass();
下列关于内部类的说法不正确的是
A)内部类的类名只能在定义它的类或程序段中或在表达式内部匿名使用
B)内部类可以使用它所在类的静态成员变量和实例成员变量
C)内部类不可以用abstract修饰符定义为抽象类
D)内部类可作为其他类的成员,而且可访问它所在类的成员
答案:C,内部类可以是抽象的。
一个类和接口同时拥有一个命名的变量a,一个子类分别继承和实现它们,不能直接访问变量a,因为不知道到底访问那个变量,可以才有以下方式访问 super.a this.a interface_name.a
一个父类和接口同时拥有一个同名的方法,父类实现了这个同名方法,如果一个子类直接继承和实现,子类是空的,直接调用方法,会调用父类的方法,同时父类的方法隐含地实现了接口的方法。
如果父类注释掉父类的方法,子类需要实现接口的方法。
如果没有去掉父类的方法,子类实现了这个方法,提示的是子类重写父类方法。
java泛型
instanceof 不能判断泛型,会编译错误,instanceof class<String>
import
import static 1.5的特性,会导入这个包或者类下的静态成员( 静态变量,静态方法 ) 直接能够使用,不用添加class.static 类限定名
右移
>>
>>>无符号移动,如果一个数是整数,那么移位的结果相同,如果数是负数,那么结果不相同
集合
ArrayList 的初始化大小是10,增量按照1.5倍增长
类加载
classloader.loadClass("classname") ;这条语句是把类加载到内存中
class.forName("class") ; // 这种情况是 5 种对 类 进行初始化的情况之一,通过反射
不会触发类的初始化:
访问类的 static final 静态常量(基本类型和字符串)不会触发初始化 类对象 // 但如果static final 修饰的类属性是 引用类型,比如new String("jk") ; 那么需要类初始化。
.class 不会触发初始化
创建该类的数组不会触发初始化
参数传递:
Java中只有值传递,String , Integer 等对象都是不可变的,及final 修饰的,传递给方法参数时,原来的引用没有发生变化,会创建一个新的引用指向方法接受的。
java的方法参数也能被final修饰
如果一个类有两个方法,method(Object o) method(String s) , 现在调用这个方法,method(null) ,实际调用的是method(String s)这个方法,因为根据Java的参数判断,String 和 Object 都能接受null,但是String是子类,更解决null,所有调用的方法是第二个。
Java序列化
序列化只是序列化对象的属性,而不会保存方法。
如果父类实现了Serializable,那么子类自动化序列化
子类序列化时,如果父类没有实现接口,如果父类拥有无参的构造方法,那么子类也能序列化父类。 但是父类属性值会丢失
static属性不能被序列化
当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化
JVM虚拟机和垃圾回收
垃圾回收的线程优先级相当低;GC程序开发者只能推荐回收,至于JVM何时进行,回收那些内存空间,程序员不能进行控制;垃圾回收只是回收那些不再使用的JVM内存,如果有严重的BUG,也会造成内存泄漏;进入DEAD的线程,也能再次恢复,不被回收。
JVM垃圾回收器分类
串行垃圾回收器:新生代使用 复制算法;老年代使用 标记压缩算法; SerialGC 新生代和老年代都能使用
并行垃圾回收器:算法同串行相同,新生代 ParNewGC, ParallerGC ,ParallerGC 关注吞吐量 ;老年代使用 ParallerOldGC
CMS 垃圾回收器,新生代和老年代都能使用,关注的是 停顿时间,使用的是标记清除算法,缺点是产生空间碎片
G1 垃圾回收器,新生代和老年代都能使用,使用的是分区算法
shell
大于或大于等于 ge gt
开启子shell sh bash ./ 不开启子shell source
增加执行 r4 w 2 x1
chmod 755 / chmod a+x /chmod u+x //u =owner , o=other
函数:函数声明可以不写关键字function , 而函数调用的正确方式是直接写函数名,不需要加上括号。 function_name
计算问题
字符串
若串S=”UP!UP!JD”,则其子串的数目。一共八个字符| U | P | ! | U | P | ! | J | D |,子串必须连续,不考虑重不重复。8+7+6+5+4+3+2+1,(1+8)*8/2=36,然后再加上一个空串,所以一共37。
堆栈
有n个数组成的序列,现在要把它们存入堆栈后,再出来,有多少种方式,C(2n,n)/ (n+1) 种。
二叉树
节点问题:叶子节点等于度为2节点加上1 , n0=n2+1 ; n=n0+n1+n2
平衡树,的树高等于 high=log2(n) n是二叉树的节点数量
数据库索引:
普通索引
唯一索引,值必须是唯一的,但允许为NULL,如果是组合索引,那么列值的组合必须唯一。
全文索引,只有在 char varchar text字段能建立,5.6以前版本只有MyISAM支持,5.6以后Innodb也支持 ; 和常用的模糊匹配使用 like + % 不同,全文索引有自己的语法格式,使用 match 和 against 关键字 ,match必须指出全文索引的列,全文索引比普通的模糊匹配效率高,但是可能会存在精度问题。
组合索引(最左前缀) :有两个以上的列值 ,比如如果在3个字段上建立索引,(state, city ,zip ) 根据最左前缀原则,它只能匹配以下字段才会用到索引 state , state city , state city zip 。
组合索引的使用场景:全字段匹配,匹配部分最左前缀,匹配第一列,匹配第一列范围查询(可用用like a%,但不能使用like %b),精确匹配某一列和范围匹配另外一列 where order by 可以使用如上5种情况的
例如,建立多列索引(name, age, id),只能使用索引的前两列。in是范围查询
... where name='nginx.cn' and age in(15,16,17) order by id || 使用整个索引,in是按值查询 ... where name='nginx.cn' and age in(15,16,17) and id ='3'
索引失效情况:
查询中有 or ,
注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
组合索引,不按照最左前缀原则使用索引
like查询,使用%开头
如果列类型是字符串,条件数据中的值 需要用 引号 把字符串包起来
进行控制判断 is null , is not null, != ,< >,
在索引列上做操作,比如计算,函数,手动,自动类型转换,会导致索引失效
SQL语句的子类: 数据定义语言DDL 数据查询语言DQL 事务控制语言TCL ; 数据插入语言不是SQL语句的子类
数据库中不能回滚的SQL语句:
DML是数据控制语句,包括SELECT,INSERT,UPDATE,DELETE,可以用ROLLBACK回滚操作或COMMIT提交操作
DDL是数据定义语句,包括CREATE,DROP,ALTER,不可进行事务操作,不能回滚,授权和权限撤销语句也没有回滚一说。
理解数据库的隔离级别
读未提交-- 事务没有提交,人能观察到最新的数据,这是脏读,解决办法是读已提交。
读已提交-- 事务提交后,但是在数据更新,在另一个事物中相同的查询条件,查到不相同的数据,这是 不可重复读,对应的是数据的UPDATE操作。
可重复读-- 事物开启,不允许其他事务进行数据的UPDATE操作,但是因为有insert操作,可以造成幻读,在事务中查询的结果会有意外的数据,就是别的事务进程插入操作。
序列化--
https://blog.csdn.net/qq_33290787/article/details/51924963
数据库
drop 删除数据和表
delete 隐藏数据,数据不可见,主键不清空,继续增长
truncate 删除数据,主键归0