Java基础
正则表达式相关
什么是正则表达式? 正则表达式可以做什么?
-
正则表达式定义了字符串的模式。
-
正则表达式可以用来搜索、编辑或处理文本。
-
正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。
-
正则表达式就是能够给出具体的限定规则
java.util.regex 包主要包括以下三个类:
-
Pattern 类:
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
-
Matcher 类:
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
-
PatternSyntaxException:
PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
1.请你谈谈Java中是如何支持正则表达式操作的?
答:java中的String类有着很多对字符串进行限定和操作的方法 比如split()、subString()、concat()、replace()、replaceFirst()、replaceAll()、matches()…此外Pattern类表示正则表达式对象,它提供了丰富的API进行各种正则表达式操作。
2.请你说明一下,在Java中如何跳出当前的多重嵌套循环?
答:break就直接跳出多重循环,而continue则可以跳出当前循环。
3.请你讲讲&和&&的区别?
答:&是位运算符或者逻辑与 而&&是短路与运算(逻辑与强调的是需要同时满足&&两边的需求)
逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true整个表达式的值才是true。&&之所以称为短路运算是因为,如果&&左边的表达式的值是false,右边的表达式会被直接短路掉,不会进行运算。
运算规则:
0&0=0;0&1=0;1&0=0;1&1=1
即:两个同时为1,结果为1,否则为0
例如:3&5
十进制3转为二进制的3:0000 0011
十进制5转为二进制的5:0000 0101
结果:0000 0001 ->转为十进制:1
即:3&5 = 1
4. int和Integer有什么区别?
答:int是整数型基本数据类型、Integer是包装类 (一个是基本数据类型一个是包装类)之所以引入Integer是为了能够将这些基本数据类型当成对象操作其次int和Integer能进行相互转化 int转Integer我们称为装箱 反之称为拆箱。
5.我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,请你讲讲如何输出一个某种编码的字符串?
答:String类的getBytes()方法就能传入各种编码字符 你只需要传入字符串就能好够按照要求显示输入内容
public byte[] getBytes(String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null) throw new NullPointerException();
return StringCoding.encode(charsetName, coder(), value);
}
public static String translate (String str) {
String tempStr ="";
try {
tempStr = new String(str.getBytes("utf-8")); //这里可以是"iso8859-1",也可以是"GBK"等等
}
catch (Exception e) {
System.err.println(e.getMessage());
}
return tempStr;
}
6.请你说明String 、StringBuffer、StringBuilder的区别
答:简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 **String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,这样不仅效率低下,而且大量浪费有限的内存空间,所以经常改变内容的字符串最好不要用 String 。**因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。
相较而言StringBuffer和StringBuilder都是操作一些可变或者经常发生变化的字符串,都具有缓冲区可以存储任意类型的数据。StringBuilder是单线线程操作字符串线程不安全、StringBuffer相对来说是多线程操作字符串,线程安全。由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。
小结:
- 如果要操作少量的数据用 String;
- 多线程操作字符串缓冲区下操作大量数据 StringBuffer;
- 单线程操作字符串缓冲区下操作大量数据 StringBuilder。(多用)
StringBuffer线程安全的原因:因为他对这些方法的操作都加上了synchronized同步方法
@Override
public synchronized StringBuffer append(Object obj) {
toStringCache = null;
super.append(String.valueOf(obj));
return this;
}
7.请你讲讲数组(Array)和列表(ArrayList)的区别?什么时候应该使用Array而不是ArrayList?
答:Array和ArrayList的不同点:
- Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。但是需要注意的是:Array数组在存放的时候一定是同种类型的元素。ArrayList就不一定了,因为ArrayList可以存储Object。
- Array大小是固定的,ArrayList的大小是动态变化的。ArrayList的空间是动态增长的,如果空间不够,它会创建一个空间比原空间大约0.5倍的新数组。newCapacity=oldCapacity+(oldCapacity>>1)
- ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
- 对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。
适用场景:使用时要看情况,基于效率和类型检验一般情况下都使用数组,简明来说ArrayList是Array的复杂版本,其内部封装了一个Object[]而已。
8.请你讲讲LinkedList和ArrayList的区别?什么时候应该使用LinkedList而不是ArrayList?
答:LinkedList和ArrayList的区别:
- ArrayList:因为Array是基于索引(index)的数据结构,它使用索引在数组中搜索和读取数据是很快的,可以直接返回数组中index位置的元素,因此在随机访问集合元素上有较好的性能。Array获取数据的时间复杂度是O(1),但是要插入、删除数据却是开销很大的,因为这需要移动数组中插入位置之后的的所有元素。
- LinkedList:相对于ArrayList,LinkedList的随机访问集合元素时性能较差,因为需要在双向列表中找到要index的位置,再返回;但在插入,删除操作是更快的。因为LinkedList不像ArrayList一样,不需要改变数组的大小,也不需要在数组装满的时候要将所有的数据重新装入一个新的数组,这是ArrayList最坏的一种情况,时间复杂度是O(n),而LinkedList中插入或删除的时间复杂度仅为O(1)。ArrayList在插入数据时还需要更新索引(除了插入数组的尾部)。
- LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素
ArrayList和LinkedList适用场景:
(1)如果应用程序对数据有较多的随机访问,ArrayList对象要优于LinkedList对象;
(2) 如果应用程序有更多的插入或者删除操作,较少的数据读取,LinkedList对象要优于ArrayList对象;
(3)不过ArrayList的插入,删除操作也不一定比LinkedList慢,如果在List靠近末尾的地方插入,那么ArrayList只需要移动较少的数据,而LinkedList则需要一直查找到列表尾部,反而耗费较多时间,这时ArrayList就比LinkedList要快。
总结:具体问题具体分析,效率问题都是相对的。
9.请你解释什么是值传递和引用传递?
答:值传递:
- 值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。
- 值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数
引用传递:
- 所谓引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
总结:值传递不改变原有值,引用传递会改变原有值。
10.请你说说Lamda表达式的优缺点。
答:Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。同时JDK 也提供了大量的内置函数式接口供我们使用,使得 Lambda 表达式的运用更加方便、高效。
-
优点:1. 简洁。2. 非常容易并行计算。3. 可能代表未来的编程趋势。
-
缺点:1. 若不用并行计算,很多时候计算速度没有比传统的 for 循环快。(并行计算有时需要预热才显示出效率优势)2. 不容易调试。3. 若其他程序员没有学过 lambda 表达式,代码不容易让其他语言的程序员看懂。
11. 你知道java8的新特性吗,请简单介绍一下
- Lambda 表达式 − Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中。
- 方法引用− 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
- 默认方法− 默认方法就是一个在接口里面有了一个实现的方法。
- 新工具− 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
- Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
- Date Time API − 加强对日期与时间的处理。
- Date Time API − 加强对日期与时间的处理。
- Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。
12.请你解释为什么重写equals还要重写hashcode?
答:
- 如果只重写equals,那么即便判断他们为同一个对象,但是如果出现hashcode不相等的时候,是不是存在同一个对象存储在两个地方,这明显不符合哈希表的存储原理。
- 反过来看,如果只重写hashcode方法而不重写equals方法,那就是默认使用Object的equals方法直接看他们是否是同一个对象,这明显也不符合(因为hashcode相同并不一定是同一个对象)
- HashMap用来判断key是否相等的方法,其实是调用了HashSet判断加入元素是否相等。重载hashCode()是为了对同一个key,能得到相同的Hash Code,这样HashMap就可以定位到我们指定的key上。重载equals()是为了向HashMap表明当前对象和key上所保存的对象是相等的,这样我们才真正地获得了这个key所对应的这个键值对。
13.请你介绍一下map的分类和常见的情况
答:java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类,分别是HashMap Hashtable LinkedHashMap 和TreeMap.(间接实现Map接口)
- Hashmap 是一个最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。 HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。
- Hashtable与 HashMap类似,它继承自Dictionary类,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了 Hashtable在写入时会比较慢。(hashtable的子类Properties与io流结合使用)
- LinkedHashMap 是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比 LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。
- TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。
总结:一般情况下,我们用的最多的是HashMap,在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。如果需要输出的顺序和输入的相同,那么用LinkedHashMap 可以实现,它还可以按读取顺序来排列.