集合方面
1.常用集合:
Map和Collection接口是所有集合框架的父接口:
1)Collection接口的子接口包括:Set接口和List接口
2)Map接口的实现类主要有:HashMap,TreeMap,Hashtable,ConcurrentHashMap以及Properties等。
3)Set接口的实现类主要有:HashSet,TreeSet,LinkedHashSet等。
4)List接口的实现类主要有ArrayList,LinkedList,Statck以及Vector等。
2.list和set和map的区别
List 可以通过下标 (1,2…) 来取得值,值可以重复。
Set 只能通过游标来取值,并且值是不能重复的。
Map 是键值对集合。
3.哪些集合类是线程安全的
1)vextor:比ArrayList多个同步化机制(线程安全),不过效率较低。
2)statck:堆栈类,先进后出。
3)HashTable:比HashMap多个线程安全。
4.arraylist和linkedlist的区别
1)ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表结构。
2)对于随机访问的get和set方法,ArrayList要优于LinkedList,因为LinkedList要移动指针。
3)对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。
5.常见的排序方式
1)冒泡排序
所谓冒泡排序就是从前到后遍历选出最大值放到最后一个,然后在遍历剩下的找出剩
下中最大的放到倒数第二个,依次直至遍历到最后一个,也就是最小的放到第一个,
使其有序。
public static void main(String[] args) {
int []array={1,3,5,4,2};
int tmp=0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length-1; j++) {
if(array[j]>array[j+1]){
tmp=array[j];
array[j]=array[j+1];
array[j+1]=tmp;
}
}
}
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
第一个for循环控制比较几遍,第二个for循环控制比较次数(比较相邻两个中比较大的值)。
2)选择排序
从第一个元素开始,用每一个元素和剩下的所有元素进行比较,如果比他小的话就交换,使第一次循环后最后一个元素是最小的值。和冒泡排序基本相反。
public static void main(String[] args) {
int []array={1,3,5,4,2};
int tmp=0;
int min;
for (int i = 0; i < array.length; i++) {
min=i;
for (int j = i+1; j <array.length ; j++) {
if(array[min]>array[j]){
tmp=array[min];
array[min]=array[j];
array[j]=tmp;
}
}
}
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
3)插入排序
从第二个元素开始插入,小的插到大的前面,然后使其有序,第三个元素在进行比较找到合适的位置插入,使前三个元素有序,以此例推。
public static void main(String[] args) {
int []array={1,3,5,4,2};
int tmp=0;
int j;
for (int i = 1; i < array.length; i++) {
tmp=array[i];
for ( j = i-1; j >=0; j--) {
if(array[j]>tmp){
array[j+1]=array[j];
}else {
break;
}
}
array[j+1]=tmp;
}
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
6.遍历集合删除元素
由于集合的长度是可变的,正常使用for循环删除元素后,集合的大小就发生了变化,对应的索引也就发生了变化会能跳过我们所删除的元素。而使用增强for遍历删除这样会导致运行时报ConcurrentModificationException异常。
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("aa");
list.add("aa");
list.add("bb");
list.add("cc");
list.add("dd");
//删除索引i=0的aa元素后,此时list集合长度发生变化,原本索引是1的aa的索引变为了0,
// 但是此时查询的索引已经变为了1,所以就跳过了第二个aa变为了查询bb了。
for (int i = 0; i < list.size(); i++) {
if(list.get(i).equals("aa")){
list.remove(i);
}
}
//运行时报ConcurrentModificationException异常
// for (String s : list) {
// if(s.equals("bb"))
// list.remove(s);
// }
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println(list.size());
}
1)iterator迭代器遍历删除:
//迭代器遍历删除
Iterator<String> it = list.iterator();
while (it.hasNext()){
String next = it.next();
if(next.equals("aa")){
it.remove();
}
}
2)反向遍历删除
//反向for循环
for (int i = list.size()-1; i >=0; i--) {
if(list.get(i).equals("aa")){
list.remove(i);
}
}
7.for循环,增强for循环和迭代器的区别
1)迭代器是用于方便集合遍历的,实现了Iterable接口的集合都可以使用迭代器来遍历。使用迭代器遍历元素时,除了查看之外,只能做remove操作。
2)增强for循环,内部使用的是迭代器,所以它的操作对象是数组和可以使用迭代器的集合。遍历时只能查看,无法修改、删除、增加。
3)如果需要对遍历的对象做增删修改的操作,使用普通的for循环来操作
8.ArrayList 和 Vector 的相同点和不同点
相同点:这两个类都实现了 List 接口(List 接口继承了 Collection 接口),他们都是有序集合,即存储在这两个集合中的元素位置都是有顺序的,相当于一种动态的数组,我们以后可以按位置索引来取出某个元素,并且其中的数据是允许重复的。
不同点:
1)同步性:Vector 是线程安全的,也就是说它的方法之间是线程同步(加了synchronized 锁)的,而 ArrayList 是线程不安全的,它的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使用 ArrayList,因为它不考虑线程安全的问题,所以效率会高一些;如果有多个线程会访问到集合,那最好是使用 Vector,因为不需要我们自己再去考虑和编写线程安全的代码。
2)数据增长:ArrayList 与 Vector 都有一个初始的容量大小,当存储进它们里面的元素的个人超过了容量时,就需要增加 ArrayList 和 Vector 的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元,每次增加的存储单元的个数在内存空间利用与程序效率之间要去的一定的平衡。Vector 在数据满时(加载因子1)增长为原来的两倍(扩容增量:原容量的 2 倍),而 ArrayList 在数据量达到容量的一半时(加载因子 0.5)增长为原容量的 (0.5 倍 + 1) 个空间。
9.HashMap和TreeMap的区别
1)HashMap是无序的,TreeMap是升序的
2)HashMap底层是哈希表,TreeMap是树结构
3)HashMap的key可以为空,TreeMap的key值不能为空
10.Hashmap和Hashtable的区别
HashMap是线程不安全的,在多线程下为了保证数据的安全,我们可以用HashTable,但是效率低。HashTable不支持null,hashMap支持null。
11.HashMap为什么是线程不安全
1)jdk多线程下扩容会出现死循环,每次添加一个数据时,底层都会去判断是否需要扩容
2)在扩容时相当于新建一个数组,那么数组上的链表也会重新添加,关键问题在于,他的数据是插入在链表的头部,后面会引起链表的死循环。1.8之后改为插入在链表的尾部。
整理借鉴了很多大佬写的,在此无法一一说明,这只是个人用来查漏补缺的文章,如果对你有帮助我很高兴。