引用
https://zhuanlan.zhihu.com/p/74229762
https://baike.baidu.com/item/JIT%E7%BC%96%E8%AF%91%E5%99%A8
https://www.runoob.com/java/java-regular-expressions.html
基础
java 编译相关
- Java程序从源文件创建到程序运行要经过两大步骤:
- 源文件由编译器编译成字节码(ByteCode),Java编译一个类时,如果这个类所依赖的类还没有被编译,编译器就会先编译这个被依赖的类,然后引用,否则直接引用
- 字节码由java虚拟机解释运行,大致视为类的加载,类的执行两个步骤。JVM主要在程序第一次主动使用类的时候,才会去加载该类
- JIT是一种提高程序运行效率的方法。通常,程序有两种运行方式:静态编译与动态解释。静态编译的程序在执行前全部被翻译为机器码,而动态解释执行的则是一句一句边运行边翻译。
java 正则表达式
捕获组概念:通过()
从左往右表示捕获组,例如,表达式((A)(B(C)))
有四个捕获组,整个表达式是第一个捕获组。
((A)(B(C)))
(A)
(B(C))
(C)
public static void main( String[] args ){
// 按指定模式在字符串查找
String line = "This order was placed for QT3000! OK?";
String pattern = "(\\D*)(\\d+)(.*)";
// 创建 Pattern 对象
Pattern r = Pattern.compile(pattern);
// 现在创建 matcher 对象
Matcher m = r.matcher(line);
System.out.println(m.groupCount());
if (m.find( )) {
System.out.println("Found value: " + m.group(0) );
System.out.println("Found value: " + m.group(1) );
System.out.println("Found value: " + m.group(2) );
System.out.println("Found value: " + m.group(3) );
} else {
System.out.println("NO MATCH");
}
}
m.groupCount()
用以获取捕获组数量,代表整个表达式的m.group(0)
不计入
3
Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT
Found value: 3000
Found value: ! OK?
- Pattern类
pattern(模式)对象是一个正则表达式的编译表示,用来保存正则表达式和生成Matcher等。
// 创建 Pattern 对象
Pattern r = Pattern.compile(pattern,0);
public static Pattern compile(String regex, int flags)
/*后面的flags代表匹配模式,包含
CASE_INSENSITIVE:不区分大小写
MULTILINE:多行模式
DOTALL:匹配任意字符,包括行终止符
LITERAL:文字分析模式
COMMENTS:允许空格和注释符`#`,#行后的与空格将被忽略
*/
- Matcher类
Matcher 对象是对输入字符串进行解释和匹配操作的引擎
// 创建 matcher 对象
Matcher m = r.matcher(line);
lambda 并行运算
- parallelStream()并行流,通过函数式编程,轻松实现并行运算
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i <= 10; i++) {
list.add(i);
}
list.parallelStream().forEach(System.out::println);
}
结果
6
7
5
10
2
1
0
3
9
8
4
为什么重写equals还要重写hashcode
- HashMap中,如果要比较key是否相等,要同时使用这两个函数!HashMap中的比较key是这样的,先求出key的hashcode(),比较其值是否相等,若相等再比较equals(),若相等则认为他们是相等的
重载hashCode()是为了对同一个key,能得到相同的Hash Code,这样HashMap就可以定位到我们指定的key上。重载equals()是为了向HashMap表明当前对象和key上所保存的对象是相等的,这样我们才真正地获得了这个key所对应的这个键值对。
ps:(==在原始数据时比较值,对象比较地址)
六原则一法则
- 单一职责原则:一个类只做它该做的事情(高内聚)
- 开闭原则:对扩展开放,对修改关闭(抽象是关键,封装要可变)
- 依赖倒转原则:面向接口编程,尽可能使用抽象类型而不用具体类型(低耦合)
- 里氏替换原则:子类可以扩展父类功能,但不能改变其原有功能(前置宽松,后置严格)
- 接口隔离原则:接口要小而专,绝不能大而全(高内聚)
- 合成聚合复用原则:优先使用聚合或合成关系复用代码
- 迪米特法则:一个对象应当对其他对象有尽可能少的了解,只用接口?
Static Nested Class 和 Inner Class的不同
- Inner Class内部类分为四种:成员内部类、局部内部类、匿名内部类和静态内部类
内部类就是在一个类的内部定义的类
内部类中不能定义静态成员(可定义静态常量,因为内部类依赖于外部类实例,非静态内部类并不随外部类一起加载,只有在实例化外部类之后才会加载。)
内部类可以直接访问外部类中的成员变量
内部类可以定义在外部类的方法外面,也可以定义在外部类的方法体中
在方法体外面定义的内部类的访问类型可以是public,protecte,默认的,private等4种类型
方法内部定义的内部类前面不能有访问类型修饰符,可以使用 final 或 abstract 修饰符
创建内部类的实例对象时,一定要先创建外部类的实例对象,然后用这个外部类的实例对象去创建内部类的实例对象
内部类里还包含匿名内部类,即直接对类或接口的方法进行实现,不用单独去定义内部类
StringBuffer和StringBuilder的区别
- StringBufferd类是线程安全的,支持并发操
- StringBuilder类不是线程安全的,但其在单线程中的性能比StringBuffer高。
- StringBufferd类中很多方法使用synchronized 修饰
String是否能能继承?
public final class String ...{
...
private final char value[];
...
}
- String 是用final修饰的,故不能,其内部数组也是,故String不可变(1.9以后用byte实现)
String为什么不可变?
- String 类被声明为一个 final 类,且类内部的 value 字节数组也是 final 的
- 不同的字符串变量都指向池中的同一个字符串
- 因为字符串是不可变的所以在它创建的时候 hashcode 就被缓存了,不变性也保证了 hash 码的唯一性,不需要重新计算,这就使得字符串很适合作为 Map 的键,字符串的处理速度要快过其它的键对象,因为字符串是不可变的,所以是多线程安全的。
Java中是否可以覆盖(override)一个static的方法?
- Java中static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。
集合
- List以特定索引来存取元素,可以有重复元素
- Set不能存放重复元素(用对象的equals()方法来区分元素是否重复)
- Map保存键值对(key-value pair)映射,映射关系可以是一对一或多对一,键不能重复
Collection 和 Collections的区别
- Collection是集合类的上级接口,继承与他的接口主要有Set 和List.
- Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
快速失败(fail-fast)和安全失败(fail-safe)的区别
- 快速失败
在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加、删除、修改),则会抛出Concurrent Modification Exception。
集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历。
java.util包下的集合类都是快速失败的,不能在多线程下发生并发修改(迭代过程中被修改) - 安全失败
采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。
基于拷贝内容的优点是避免了Concurrent Modification Exception,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。
java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。
Iterator和ListIterator的区别
- Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
- Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
ArrayList是否会越界
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
多线程同时增加时,可能会越界
hashMap的key是一个自定义的类,怎么办?
- 使用HashMap,如果key是自定义的类,就必须重写hashcode()和equals()。
在ArrayLIst和LinkedList尾部加元素,谁的效率高?
- ArrayLIst时间损耗在于扩容
- LinkedList时间损耗在于new Node
故而小数据时LinkedList优,大数据时ArrayLIst优