1:集合遍历,要删除其中一个元素
要想在集合遍历的过程中删除指定元素,就务必使用迭代器自身的remove方法;
可以使用 Iterator 本身的方法 remove() 来删除对象,
这种方式可以正常的循环及删除。但要注意的是,使用iterator的remove方法。
2:ArrayList排序
java中实现对list的自定义排序主要通过两种方式
1)让需要进行排序的对象的类实现Comparable接口,重写compareTo(T o)方法,在其中定义排序规则,那么就可以直接调用Collections.sort()来排序对象数组
2)实现比较器接口Comparator,重写compare方法,直接当做参数传进sort中
我们通常使用Collections.sort()方法来对一个简单的数据列表排序。
但是当ArrayList是由自定义对象组成的,就需要使用comparable或者comparator接口了。
倒序:
// Collections.sort(list, new Comparator<CoterieTag>(){
// /*
// * int compare(CoterieTag o1, CoterieTag o2) 返回一个基本类型的整型,
// * 返回负数表示:o1 小于o2,
// * 返回0 表示:o1和o2相等,
// * 返回正数表示:o1大于o2。
// */
// public int compare(CoterieTag o1, CoterieTag o2) {
// //按照命中次数进行升序排列
// if(o1.getHitNumber() > o2.getHitNumber()){
// return 1;
// }
// if(o1.getHitNumber() == o2.getHitNumber()){
// return 0;
// }
// return -1;
// }
// });
正序:
Collections.sort(list, new Comparator<CoterieTag>(){
/*
* int compare(CoterieTag o1, CoterieTag o2) 返回一个基本类型的整型,
* 返回负数表示:o1 小于o2,
* 返回0 表示:o1和o2相等,
* 返回正数表示:o1大于o2。
*/
public int compare(CoterieTag o1, CoterieTag o2) {
//按照命中次数进行升序排列
if(o1.getHitNumber() > o2.getHitNumber()){
return -1;
}
if(o1.getHitNumber() == o2.getHitNumber()){
return 0;
}
return 1;
}
});
}
public class Test {
public static void main(String[] args) {
List<Student> list = new ArrayList<Student>();
//创建3个学生对象,年龄分别是20、19、21,并将他们依次放入List中
Student s1 = new Student();
s1.setAge(20);
Student s2 = new Student();
s2.setAge(19);
Student s3 = new Student();
s3.setAge(21);
list.add(s1);
list.add(s2);
list.add(s3);
System.out.println("排序前:"+list);
Collections.sort(list, new Comparator<Student>(){
/*
* int compare(Student o1, Student o2) 返回一个基本类型的整型,
* 返回负数表示:o1 小于o2,
* 返回0 表示:o1和o2相等,
* 返回正数表示:o1大于o2。
*/
public int compare(Student o1, Student o2) {
//按照学生的年龄进行升序排列
if(o1.getAge() > o2.getAge()){
return 1;
}
if(o1.getAge() == o2.getAge()){
return 0;
}
return -1;
}
});
System.out.println("排序后:"+list);
}
}
class Student{
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return getAge()+"";
}
}
执行结果:
[html] view plain copy
排序前:[20, 19, 21]
排序后:[19, 20, 21]
当然对象的属性可以多个,比如按年龄升序,按成绩降序等
3:Arraylist 去重,实现思路
首先说明一下ArrayList和HashSet的区别:
ArrayList是List(列表),数据是有序的,可以有重复元素。
HashSet是Set(集合),数据没有顺序,没有重复元素,元素搜索速度快。
之后我们利用ArrayList->HashSet->ArrayList后即可实现对List的去重工作,实现代码如下:
其实这个还要看集合中存的是什么,
两个例子:
1.ArrayList存储字符去重
2.ArrayList存储自定义对象去重
一 . ArrayList存储字符串去重。
思路:
a、重新new一个新的List集合。
b、然后遍历旧集合,然后获取旧集合中的每一个元素。
c、判断新集合中是否有 当前遍历到的元素。
有:就不添加。
没有:就添加。
二 . ArrayList存储存储自定义对象去重
这个和第一种情况思路大同小异,不同之处是集合内存储的是对象,代码上有些不同,这里我们写一个Student类来演示
需要注意的是,还要重写toString()方法和equals()方法,
重写hashCode方法,如果你是用hashCode来判断两个对象是否相等。
4:为什么数组查询比链表要快?而插入删除比链表效率低
一般来说数组的查询速度快于链表,原理是什么?
电脑中存在多种不同的存储器,如下表
- CPU 寄存器 – immediate access (0-1个CPU时钟周期)
- CPU L1 缓存 – fast access (3个CPU时钟周期)
- CPU L2 缓存 – slightly slower access (10个CPU时钟周期)
- 内存 (RAM) – slow access (100个CPU时钟周期)
- 硬盘 (file system) – very slow (10,000,000个CPU时钟周期)
各级别的存储器速度差异非常大,CPU寄存器速度是内存速度的100倍!
这就是为什么CPU产商发明了CPU缓存。
而这个CPU缓存,就是数组和链表的区别的关键所在。
CPU缓存会把一片连续的内存空间读入, 因为数组结构是连续的内存地址,
所以数组全部或者部分元素被连续存在CPU缓存里面, 平均读取每个元素的时间只要3个CPU时钟周期。
而链表的节点是分散在堆空间里面的,这时候CPU缓存帮不上忙,只能是去读取内存,平均读取时间需要100个CPU时钟周期。
这样算下来,数组访问的速度比链表快33倍! (这里只是介绍概念,具体的数字因CPU而异)
其实这里还有一个概念就是操作系统的局部性原理
1、数据存储结构分为顺序存储、链接存储、索引存储、散列存储。
2、数组属于顺序存储,用一段连续的内存位置来存储。
3、链表属于链接存储,用一组任意的存储单元来存储,不要求物理上相邻。
总结:
因为CPU缓存会读入一段连续的内存,顺序存储符合连续的内存,所以顺序存储可以被缓存处理,而链接存储并不是连续的,分散在堆中,所以只能内存去处理。
所以数组查询比链表要快。
而数组大小固定,插入和删除都需要移动元素,链表可以动态扩充,插入删除不需要移动元素,只需要更改元素中的指针。所以链表的插入删除比数组效率高。
多说一句:查询比数组快,删除插入效率又高的方式就是散列存储,散列是什么?散列的英文:hash