我们常见的Java集合类有List、Set、Map。
List
1、接口可以被继承。
2、接口可以被多次实现。
3、List和ArrayList
package List;
import java.util.ArrayList;
import java.util.List;
public class ListDemo {
public static void main(String[] args) {
//只能用list接口里的方法
List<String> list1 = new ArrayList();
//可以用ArrayList里的所有方法,因为ArrayList是实现list接口,所以可以调用的方法,比第一种要多,还可以使用list接口里面没有的方法
ArrayList list2 = new ArrayList();
}
4、如果已经确定了List里面要放的元素,不在扩容,建议用asList,性能比较高,没有扩容操作。
注意:这样写以后,不能再add
List<String> list1 = Arrays.asList("asa","qqq");
5、数组边遍历边删除删不干净。
原因:因为边遍历边删除,从index=0开始遍历,删除第一个元素,然后原数组的第二个元素就到了index=0的位置,原数组的第三个元素到了index=1的位置,但是此时遍历到了index=1,就漏过了原来的第二个元素,后面也是这样,所以数组边遍历边删除删不干净。
6、三种实现数组删除的方法。
(一)倒叙删除
package List;
import java.util.ArrayList;
import java.util.List;
public class ListDemo {
public static void main(String[] args) {
List<String> list1 = new ArrayList();
list1.add("aaa");
list1.add("aaa");
list1.add("aaa");
for(int i=list1.size()-1 ; i>=0 ; i--){
list1.remove(i);
}
}
}
(二)迭代器删除
public static void main(String[] args) {
List<String> a = new ArrayList<String>();
a.add("a");
a.add("a");
a.add("c");
a.add("d");
a.add("a");
a.add("d");
a.add("a");
Iterator<String> it = a.iterator();
while(it.hasNext()){
String temp = it.next();
if(temp.equals("a")){
it.remove();
}
}
for(int i=0;i<a.size();i++){
System.out.println(a.get(i));
}
}
(三)lambada删除
public static void main(String[] args) {
List<EliminateRecordResultMo> removeList = new ArrayList<>();
data.stream().forEach(vo ->{
if(vo.getNotCount() == 0) {
// System.out.println(vo.getOrgName());
removeList.add(vo);
}
});
data.removeAll(removeList);
}
7、List如何判空。
boolean equals = StrUtil.equals(list1.get(1), list1.get(2));
System.out.println(CollectionUtil.isEmpty(list1));
8、List不是多线程安全的。
ListDemo类
package List;
import java.util.ArrayList;
public class ListDemo {
public static void main(String[] args) {
//只能用list接口里的方法
ArrayList<String> list = new ArrayList();
MyThread m1 = new MyThread(list);
MyThread m2 = new MyThread(list);
new Thread(m1).start();
new Thread(m2).start();
}
}
MyThread类
package List;
import java.util.ArrayList;
public class MyThread implements Runnable{
ArrayList<String> aaa;
public MyThread(ArrayList<String> aaa){
this.aaa = aaa;
}
@Override
public void run() {
for (int i=0;i<100;i++){
aaa.add("aaa"+i);
System.out.println(Thread.currentThread().getName()+"在第"+i+aaa.get(i));
}
}
}
可以发现下面的运行结果,输出并不是相对应的,由此可见,线程不安全。
Set
1、list是有序可以重复的,set是无序不重复的。
2、set也不能边遍历边删除。
3、set(hashmap)是怎么判断两个对象是否相等的,底层实现是用的hashmap。
Map
1、两个对象的hashcode如果相等,这两个不一定相等,因为可能存在hash碰撞。但是两个对象的hashcode如果不相等,那么这两个对象绝对不相等。
2、hashmap判断两个key是否相等
先判断这两个对象的hashcode是否相等,如果相等,再去调用equals。如果不相等,就直接认为这两个对象不相等。
好处:equals需要比对太多元素性能较差,但Hashcode直接比较,性能较高一些。
3、两个对象的equals相等,那么这两个对象一定相等。
4、重写equals必须要重写hashcode。
两个方法中的变量要一样。
5、hashmap数据结构。
hashmap的数据结构是数组加链表(数组+红黑树),充分利用了数组和链表的优点。
使HashMap无论是get还是put,都比较快,性能较高。
hashcode和equals都不一样的,按数组加入;hashcode一样,equals不一样的,就会按链表排在后面。
6、多线程操作HashMap会发生什么。
只会影响map.keySet().size()获取到的size,不会影响实际的插入。