目录
心情日记
又是代码少,知识点多的半天,半天?是因为上午放假!๑乛v乛๑嘿嘿。总感觉就是为了要考试,所以考试前两天抓紧讲这么多知识点!脑子不太够用了,本来头发就少。。。
重点归纳
集合的各种接口及其特点
面试题
集合的遍历
并发异常问题
知识点
List
List:数据是有顺序的(添加的先后顺序),数据可以重复
ArrayList:内部结构是数组,比较适合做高频的查找,遍历
LinkedList:双向链表。添加删除时有头有尾,比较适合做高频的新增和删除
Vector:向量,和ArrayList几乎一模一样。没有ArrayList好用
面试题
1.Collection和Map接口的区别
Collection<E>:存放单值的最大父接口(泛型接口)
子接口:
List<E>(列表)线性表:和数组类似,List可以动态增长,插入和删除元素会使元素移位
Set<E>也是线性表,检索元素的效率低,删除和插入的效率高,插入和人删除元素不会使元素移位Map<K,V>:存放一对值的最大父接口(两个泛型的接口)
Map(映射):用于保存具有映射关素的数据,Map保存着两组数据:key和value
key和value都可以是任意的引用数据类型,但key不可以重复List、Set继承于Collection,Map不是
2.ArrayList和LinkedList的区别
ArrayList:List接口的实现类,内部结构是一个数组,涉及到移位,下标维护
LinkedList:List接口的实现类,内部结构是一个链表,便于增加,删除元素。
两者都是异步的,线程不安全。
3.ArrayList和Vector的区别,类似于StringBuffer和StringBuilder
ArrayList是线程异步的,线程不安全
Vector是线程同步的,线程安全
//测试一下LinkedList
public static void main(String[] args) {
// List<String> list = new LinkedList<>();
LinkedList<String> list = new LinkedList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
// 我们在创建对象的时候用的是多态
// 父类对象---子类引用
// 我们创建出来的对象只能够调用父类和子类中都有的方法
list.addFirst("z");
list.addLast("x");
list.removeFirst();
list.removeLast();
// 根据下标索引获取指定位置的元素
System.out.println(list.get(2));
System.out.println(list);
}
Comparable接口
CompareTo返回值代表什么?
int类型:代表排序结果
负数-1:表明比较两个值调用者小
0:两个值相等
1:比较两个值调用者大
重写compareTo自己可以规定排序规则
public class Person implements Comparable<Person> {
private String name;
private Integer id;
public Person(String name, Integer id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
if (!name.equals(person.name)) return false;
return id.equals(person.id);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + id.hashCode();
return result;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", id=" + id +
'}';
}
/*
返回值代表什么?
int
代表排序结果
负数-1:比较的两个值调用者小
0:两个值相等
正数1:比较的两个值调用者大
*/
@Override
public int compareTo(Person p) {
if(this.id > p.id){
return -1;
}
if(this.id.equals(p.id)){
return 0;
}
return 1;
}
List:有顺序,元素可以重复,顺序指的是添加的先后顺序
Set:没有顺序,元素不可以重复,没有顺序指的是没有按添加的先后顺序
其实是有顺序的,内部有一个专门的排序算法,所谓的无序不等于随机三大集合用的最多的是Map
面试题
1.List和Set的区别
List:有顺序,元素可以重复,顺序指的是添加的先后顺序
Set:没有顺序,元素不可以重复,顺序指的是添加的先后顺序
2.HashSet和LinkedHashSet的区别和联系
LinkedHashSet是HashSet的子类
LinkedHashset、HashSet是根据hashCode值来决定元素的存储位置
但LinkedHashset同时使用链表维护元素的次序,元素是以添加的顺序保存的
LinkedHashset性能要略低于HashSet的性能
//Set
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(Integer.valueOf(200));
set.add(4);
set.add(15);
set.add(38);
set.add(Integer.valueOf(200));
System.out.println(set);
}
引用数据类型
Set集合所谓的不能重复默认为比地址,地址不能重复
只要涉及引用数据类型,重复、比较等等都为比地址
保证Set集合元素不重复
Set集合如何确保数据的不重复?(地址不相同,数据都相同)
保证数据类型的类要重写hashCode,equals方法
public static void main(String[] args) {
Set<Person> set = new HashSet<>();
set.add(new Person("张三",1001));
set.add(new Person("张三",1001));
set.add(new Person("张三",1001));
set.add(new Person("张三",1001));
// 引用数据类型
// set集合所谓的不能重复,默认情况下比较地址
System.out.println(set);
}
TreeSet
可以排序的Set集合,默认为ASCLL码值从小到大排序
排序规则:
要排序的对象的类必须实现Comparable接口
public static void main(String[] args) {
// Set<Integer> tree = new TreeSet<>();
// tree.add(-100);
// tree.add(100);
// tree.add(10);
// tree.add(50);
// Set<String> tree = new TreeSet<>();
// tree.add("1");
// tree.add("a");
// tree.add("哈哈哈哈哈哈");
// tree.add("%");
Set<Person> tree = new TreeSet<>();
tree.add(new Person("张岳",1001));
tree.add(new Person("李四",1010));
tree.add(new Person("费四",1003));
System.out.println(tree);
}
LinkedHashSet
继承HashSet,有输入先后顺序,但也不能get,较率比较低
public static void main(String[] args) {
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("1");
set.add("a");
set.add("哈哈哈哈哈哈");
set.add("%");
System.out.println(set);
}
比较接口
Comparable接口:自然排序,排序规则是固定的
Comparator接口(函数式泛型接口):临时排序(什么时候用什么时候写)
public static void main(String[] args) {
List<Person> list = new ArrayList<>(16);
list.add(new Person("张岳",1100));
list.add(new Person("李四",1010));
list.add(new Person("刘海柱",1020));
// list.sort(new Comparator<Person>() {
// @Override
// public int compare(Person o1, Person o2) {
// return 0;
// }
// });
list.sort((o1,o2) -> {
if(o1.getId() < o2.getId()){
return -1;
}
if(o1.getId().equals(o2.getId())){
return 0;
}
return 1;
});
System.out.println(list);
}
Map接口
1.存储一对值的k-v :key-value
2.key不能重复
3.没有顺序(添加的先后顺序)
只能根据key值取value值
HashMap内部存储结构
JDK1.7之前:链表+二叉树
JDK1.7及之后:链表+二叉树+红黑树HashMap面试必问你原理!!!
不成文规定五年三跳,不要多跳槽,要稳定!!!
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1001","张岳");
map.put("1002","赵红兵");
map.put("1003","小北京");
map.put("1004","李四");
map.put("1004","张浩然");
map.put("1005","张浩然");
System.out.println(map);
System.out.println(map.get("1003"));
System.out.println(map.values());
System.out.println(map.keySet());
}
Hashtable实现类:(唯一一个没有驼峰的类)
面试题
Hashtable和HashMap区别
Hashtable和HashMap没啥区别,几乎一模一样
1.HashMap是线程异步的,线程不安全的
Hashtable是线程同步的,线程安全的
HashMap的key可以为null的,
Hashtable的key是不可以为null的
LinkedHashMap
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put(null,null);
System.out.println(map);
Hashtable<String, String> table = new Hashtable<>();
table.put(null,null);
System.out.println(table);
}
Properties:属性
Hashtable的子类,更多的来操作属性文件
用IO流读取属性文件
集合的遍历
List集合的遍历
1.for循环
2.foreach语句
3.迭代器
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
// 1.for循环
// for (int i = 0; i < list.size(); i++) {
// System.out.println(list.get(i));
// }
// 2.foreach语句
// for (String s : list) {
// System.out.println(s);
// }
// 3.迭代器
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
String s = iterator.next();
iterator.remove();
// System.out.println(s);
}
System.out.println(list);
}
Set集合的遍历
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(4);
set.add(15);
set.add(38);
// 1.增强for
// for (Integer integer : set) {
// System.out.println(integer);
// }
// for (int i = 0; i < set.size(); i++) {
//
// }
// 2.迭代器
Iterator<Integer> iterator = set.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
Map集合的遍历
1.for循环不太行,首先需要拿所有的key在循环
2.增强for循环
3.增强for循环
Entry是hashmap的一个内部类,每一组键值对就是一个Entry对象
4.迭代器
先拿所有的key,相当于用Set进行迭代器操作。
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1001","张岳");
map.put("1002","赵红兵");
map.put("1003","小北京");
map.put("1004","李四");
map.put("1005","张浩然");
// 1.for循环
// Set<String> strings = map.keySet();
// for (String s : strings) {
// System.out.println(s + "->" + map.get(s));
// }
// 2.增强for循环
// Set<String> strings = map.keySet();
// Collection<String> values = map.values();
// 3.增强for循环
// Entry是hashmap的一个内部类
// 每一组键值对就是一个Entry对象
// Set<Map.Entry<String, String>> entries = map.entrySet();
// for (Map.Entry<String, String> entry : entries) {
// System.out.print(entry.getKey() + "->");
// System.out.println(entry.getValue());
// }
// 4.迭代器
Set<String> strings = map.keySet();
Iterator<String> iterator = strings.iterator();
while(iterator.hasNext()) {
String s = iterator.next();
System.out.println(s + "->" + map.get(s));
}
}
并发异常问题:面试题
删除结合元素删除不干净
删除一个元素,集合能自己移位补缺,指针位置自动往下走,遍历时漏一位,可能是需要删除的元素
怎么删除干净?
1.for循环:回调指针:i--
2.逆序遍历从后往前删除
3.使用迭代器(推荐,万无一失)
(增强for循环:foreach循环操作的是镜像元素,只能遍历,不能删除真实元素。不太行)
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("tom");
names.add("lucy");
names.add("lucy");
names.add("lucy");
names.add("jerry");
// 1.for循环
// for (int i = 0; i < names.size(); i++) {
// if(Objects.equals(names.get(i),"lucy")){
// names.remove(i);
// // 1.回调指针
// i--;
// }
if("lucy".equals(names.get(i))){
}
// }
// 2.逆序遍历
// for (int i = names.size() - 1; i >= 0; i--) {
// if(Objects.equals(names.get(i),"lucy")){
// names.remove(i);
// }
// }
// 3.使用迭代器(推荐)万无一失
Iterator<String> iterator = names.iterator();
while(iterator.hasNext()) {
String s = iterator.next();
if(Objects.equals(s,"lucy")){
iterator.remove();
}
}
System.out.println(names);
}
其他集合
1.LinkedHashMap:在HashMap的基础上维护了一个双向链表。
2.TreeMap:天然支持自然排序
3.Collections:是一个工具类
面试题
线程安全的问题
并发修改异常
用普通方法遍历,但是用迭代器的方法删除元素,普通方法还在遍历,不知道新增或者删除了元素,相当于多线程操作,会出现并发修改异常
反之一样
foreach循环底层是迭代器方法,不能用普通方法删除元素
迭代器是依赖于集合存在,判断成功以后,如果是新增或删除了元素,但是迭代器不知道,所以报错了
集合需要掌握的
1.如何创建需要的集合:主要用多态
主要用List,Map
2.各种区别(面试题)
3.各种集合方法
4.两个比较接口
5.各种集合的特点:从接口的层面到实现类的层面
6.各种集合API的调用
7.重点集合的内部结构。ArrayList、HashSet、HashMap
8.各种集合的遍历
9.并发问题
10.接口、实现类的方法要去看,有个印象最重要的集合:
ArrayList和HashMap推荐学习集合顺序:List->Map->Set
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("tom");
names.add("lucy");
names.add("lucy");
names.add("lucy");
names.add("jerry");
for (String s : names) {
if(Objects.equals(s,"lucy")){
// names.remove(s);
names.add(s);
}
}
}