- 下列代码的输出结果是:
public static void main(String[] args) {
String str = “LEA”;
Deque stack = new LinkedList();
for (int i = 0; i < str.length(); i++) {
stack.push(str.charAt(i));
}
stack.pop();
stack.pop();
stack.pop();
System.out.println(stack.peek());
}
A.L B.E C.A D.null
2.请看以下代码:
Map<String,Double> map=new HashMap<String,Double>();
map.put(“tom”,123.6);
map.put(“jim”,234.5);
map.put(“jerry”,45.3);
《插入代码》
《插入代码》处要实现的功能是把key为"jim"的value值在原有数字的基础上加100
正确的是( )。
A.map.put(“jim”,map.get(“jim”)+100);
B.map.set(“jim”,map.get(“jim”)+100);
C.map.put(“jim”,234.5);
D.map.set(“jim”,234.5);
3.try{}里面有一个return语句,那么紧跟在这个try后的finally{}里的代码执行的情况:( )
A.会执行,在return前执行
B.会执行,在return后执行
C.不会执行
D.会抛出异常
简答题
1.请描述Array和ArrayList有何区别?什么时候更适合用Array?
①Array是数组,一旦初始化以后,其长度就不可修改,其元素的类型也就确定,
只能操作指定类型的数据。
数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
②:存储元素的类型: Array即可以存储基本类型也可以存储引用类型。
存放相同数据类型的元素。ArrayList只能存储引用类型,可以存放任意引用类型的数据
③ArrayList是集合的实现类,类中定义了属性和方法,可以通过无参构造创建对象,创建对象时ArrayList底层维护了一个Object[] elementData 数组,用来存储数据,JDK8之前是当创建一个ArrayList对象时,直接创建一个容量为10的数组,JDK8之后当创建一个ArrayList对象时,创建一个空数组,为了优化内存,相当于延迟分配对象数组空间:
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};,ArrayList相当于可变的数组,当第一次添加元素时,扩容为长度为10的数组,当超过第十个时,底层源码会自动扩容到当前数组的1.5倍,底层源码为:
int newCapacity = oldCapacity + (oldCapacity >> 1);
①:当需要存储固定大小的基本数据类型时,使用Array更适合,因为使用ArrayList底层还要进行自动装箱操作,还要进行数组扩容等操作麻烦
②:当需要存储元素类型相同的数据时可以使用数组。
2.ArrayList,LinkedList和Vector的区别
相同点:都实现了List接口,存储数据的特点相同:存储有序的、可重复的数据
不同点:
- ArrayList和Vector底层是数组,查询数据快
- LinkedList底层是链表,增删快。
- ArrayList 和 Vector 的区别在于ArrayList是线程不安全的,Vector是线程安全的,ArrayList的执行效率要略高于Vector.
3.简述ArrayList的扩容原理
ArrayList底层维护了一个Object[] elementData 数组,用来存储数据,JDK8之前是当创建一个ArrayList对象时,直接创建一个容量为10的数组,JDK8之后当创建一个ArrayList对象时,创建一个空数组,为了优化内存,相当于时延迟分配对象数组空间: private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
(什么时候分配容量:)当第一次插入元素时才扩容为一个长度为 10(默认)的对象空间。即第一次调用add添加数据时分配;
- transient Object[] elementData;
- private static final int DEFAULT_CAPACITY = 10;
- 当超过10个元素时,底层会自动扩容,扩容的方式(底层源码)是:
- int newCapacity = oldCapacity + (oldCapacity >> 1);
- 即扩容至原容量的1.5倍。
4.LinkedList如何进行元素的查找
①可以通过get(int index); LinkedList的public E get(int index)实现机制: 比较传入的索引值index与集合长度size/2,
如果是index小,那么从第一个元素开始循环,直到找到为止;
如果是index大,那么从最后一元素开始倒序循环,,直到找到为止。也就是说,越靠近中间位置的元素,调用get()方法遍历的次数越多,效率就越低,而且随着集合越来越大,get()方法的执行性能也会下降,因此使用LInkedList的时候,不建议使用这种方式读取数据, 可以使用getFirst(),getLast()直接获取集合中第一个和最后一个元素
5.什么是队列?什么是双端队列?什么是栈?存取元素时有什么特点?
队列:队列可以保存一组元素,存取元素必须遵循先进先出(FIFO:Fist in First Out)的原则。
双端队列:Deque继承自Queue,特点是队列两端都可以做出入队操作。
栈:栈可以保存一组元素,存取元素必须遵循先进后出(FILO 或 LIFO(后进先出))原则。通常使用栈结构完成“ 后退 "功能。
实现:创建栈有两种方式:
Deque 双端队列如果从同一侧做出入栈操作就实现了栈结构,因此Deque也为栈,提供它出入栈的典型方法:push,pop
入栈也称为压栈,出栈也叫弹栈。出栈时获取数据后,原数据会从栈中移除
6.遍历Map的方式
Map提供了三种遍历方式:
- 1.遍历所有的key
Map接口提供了一个返回值类型为Set的抽象方法keySet();
将当前Map中所有的key以一个Set集合的形式返回。
遍历该集合等同于遍历Map中所有的key。
- 2.遍历所有的键值对
Map提供了entrySet()方法
Set<Entry> entrySet()
将当前Map中的每一组键值对以若干个Entry实例保存,
并且存入一个Set集合后返回。
java.util.Map.Entry
该接口的每一个实例用于表示Map中的一组键值对
该接口提供了两个常用方法:
K getKey() V getValue()
- 3.遍历所有的value(相对不常用,因为value是可重复的)
Map提供了返回值为Collection的 values()方法,
Collection<V> values()
将当前Map中的所有value以一个集合形式返回
遍历该集合等同于遍历Map中的所有的Value。
- 三种方式都可以通过新循环、forEach()方法遍历
编程题
- 已知某学校的教学课程内容安排如下:
- 教师 课程名
- Tom CoreJava
- John Oracle
- Susan Oracle
- Jerry JDBC
- Jim Unix
- Kevin JSP
- Lucy JSP
完成下列要求:
1) 使用一个Map,以老师的名字作为键,以老师教授的课程名作为值,表示上述课程安排。
2) 增加了一位新老师Allen 教JDBC
3) Lucy 改为教CoreJava
4) 遍历Map,输出所有的老师及老师教授的课程
5) 利用Map,输出所有教JSP 的老师。
public class MapTest1 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
//向散列表中添加元素
//1) 使用一个Map,以老师的名字作为键,以老师教授的课程名作为值,表示上述课程安排。
map.put("Tom","CoreJava");
map.put("John","Oracle");
map.put("Susan","Oracle");
map.put("Jerry","JDBC");
map.put("Jim","Unix");
map.put("Kevin","JSP");
map.put("Lucy","JSP");
//2) 增加了一位新老师Allen 教JDBC
map.put("Allen","JDBC");
//3) Lucy 改为教CoreJava
map.put("Lucy","CoreJava");
System.out.println("-----------使用Map.Entry<K,V>遍历----------------");
//4) 遍历Map,输出所有的老师及老师教授的课程
// ①使用Map.Entry遍历map,返回的是
Set<Map.Entry<String ,String>> entrySet = map.entrySet();
map.forEach((k,v) -> System.out.println(k + " = " + v));
//②使用新循环遍历
System.out.println("----------使用新循环------------");
for (Map.Entry<String,String> m : entrySet){
//可以分别获取key 和 value
String key = m.getKey();
String value = m.getValue();
System.out.println(key + " = " + value);
//可以直接输出Set 集合 m (Set<Map.Entry<K ,V >>)
//System.out.println(m);
}
System.out.println("-----------教JSP的老师有-------------");
//5) 利用Map,输出所有教JSP 的老师。
for (String key : map.keySet()){
if (map.get(key).equals("JSP")){
System.out.println(key);
}
}
}
}
执行结果:
2.已知字符串“adhflkalkfdhasdkhflsa”
(1)统计去掉重复后的字符
(2)统计每个字符出现的次数
解析:要求把每个重复的字符作为Map的key存入,重复的字符次数作为Map的value。
/**
* 2.已知字符串“adhflkalkfdhasdkhflsa”
* (1)统计去掉重复后的字符
* (2)统计每个字符出现的次数
* @author yyc
* 2021/9/27 19:45
*/
public class SumString {
public static void main(String[] args) {
String str = "adhflkalkfdhasdkhflsa";
//1)统计去掉重复后的字符
// 2)统计每个字符出现的次数
Map<Character, Integer> map = new HashMap<>();
for (int i = 0; i < str.length(); i++){
//用来记录每个字母出现的次数,不能声明在循环外,也不能声明在二层循环的里面,不然每次都清零
int sum = 0;
for (int j = 0; j < str.length(); j++){
if (str.charAt(i) == str.charAt(j)){
sum++;
map.put(str.charAt(i),sum);
}
}
}
System.out.println(map);
}
}
去掉重复字符。
/**
* 2.已知字符串“adhflkalkfdhasdkhflsa”
* (1)统计去掉重复后的字符
* (2)统计每个字符出现的次数
* @author yyc
* 2021/9/27 19:45
*/
public class SumString {
public static void main(String[] args) {
String str = "adhflkalkfdhasdkhflsa";
Set<Character> charSet = new HashSet<>();
//(1)统计去掉重复后的字符
int sum = 0;
//(1)统计去掉重复后的字符
for (int i = 0; i < str.length(); i++){
for (int j = 0; j < str.length(); j++){
if (str.charAt(i) != str.charAt(j)){
charSet.add(str.charAt(i));
}
}
}
System.out.println(charSet);
}
}
执行结果: