javaCollection-随笔
集合的体系结构
Collection迭代器
1.迭代器:集合的专用遍历方式,依赖于集合存在
// 迭代器
Iterator<Student> it = collect.iterator();
- 等式的左边返回的为一个迭代器对象,赋予迭代器变量it
List集合
1.注意事项,并发修改异常
// 迭代器异常ConcurrentModificationException
for(Iterator<String> it = list.iterator();it.hasNext();){
String s = it.next();
if (s.equals("aa")){
list.add("dd");
}
}
- 这是因为List源码解析中,有段代码中会进行异常判断
// 迭代器异常ConcurrentModificationException 判断
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
- 在上一段代码中,如果在迭代器遍历过程中运行list.add方法,则会导致expectedModCount+1,因此判断不等,则报出异常。
2.解决方法1:换一种遍历方式(for循环)
// 遍历方式
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
if (s.equals("aa")){
list.add("cc");
}
}
3.解决方法2:运用列表迭代器(ListIterator)
- 介绍
- 通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
- 用于允许程序员沿任一方向遍历的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
// 遍历方式,运用了listIterator(),内部原理还是运用迭代器
ListIterator<String> lit = list.listIterator();
while (lit.hasNext()) {
String s = lit.next();
if(s.equals("world")) {
lit.add("javaee");
}
}
- 因为在lisiIterator()相关的add方法中,将变换的expectedMod赋予CountmodCount,因此判断相等时一直相等,add()方法可继续执行。
List集合的子类
- ArrayList集合:底层是数组结构实现,查询快、增删慢
- LinkedList集合:底层是链表结构实现,查询慢、增删快
因为linkedlist底层是用链表实现,因此具有表头,表尾的相关操作方法
Set集合
- 元素存取无序
- 没有索引、只能通过迭代器或增强for循环遍历
- 不能存储重复元素
HashSet集合
1.特点
- 底层数据结构是哈希表
- 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以是不包含重复元素的集合
2.注意事项:某些字符串的HashCode值可能相等
// HashCode值相等
System.out.println("重地".hashCode()); //1179395
System.out.println("通话".hashCode()); //1179395
- 因此,我们在使用HashSet的add()时,源码会通过插入数值的HashCode是找到对应的插入位置,还会通过equal()方法比较两者是否相等。若相等,则不插入,因为不能存储重复元素。
3.注意事项二:HashSet存储自定义对象可能会重复
// 实例重复
HashSet<Student> hs = new HashSet<Student>();
//创建学生对象
Student s1 = new Student("林青霞", 30);
Student s2 = new Student("张曼玉", 35);
Student s3 = new Student("王祖贤", 33);
Student s4 = new Student("王祖贤", 33);
//把学生添加到集合
hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);
- 输出为
张曼玉,35
王祖贤,33
林青霞,30
王祖贤,33
- 因此,在实际使用时,我们有可能会自己定义HashCode方法。
// 自定义HashCode部分代码
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name ==
null;
}
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
- 输出为
王祖贤,33
张曼玉,35
林青霞,30
TreeSet集合
1.特点
- 元素有序,可以按照一定的规则进行排序,具体排序方式取决于构造方法
- TreeSet():根据其元素的自然排序进行排序
- TreeSet(Comparator comparator) :根据指定的比较器进行排序
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以不包含重复元素的集合
2.注意事项1:实现Comparator 接口,需要重写方法
// 自定义Comparable部分代码
public class Student implements Comparable<Student>{
public int compareTo(Student o) {
return 0;
}
}
2.注意事项2:也可在构造方法中传递比较器接口,相应的类中不需要实现Comparator 接口
// 实现比较器接口的构造
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int num = o1.getAge() - o2.getAge();
int num2 = num == 0 ? o1.getName().compareTo(o2.getName()) : num;
return num2;
}
Map集合
- 键值对映射关系
- 一个键对应一个值
- 键不能重复,值可以重复
- 元素存取无序
- Map集合的两种遍历方式
// Map集合遍历
Map<String,String> map = new HashMap<>();
map.put("1","aa");
map.put("2","bb");
map.put("3","cc");
//方式1:Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
Set<Map.Entry<String,String>> entryset = map.entrySet();
for(Map.Entry<String,String> es : entryset){
String key = es.getKey();
String value = es.getValue();
System.out.println(key + ":" + value);
}
//方式2:获取所有键的集合。用keySet()方法实现
Set<String> set = map.keySet();
for(String s : set){
System.out.println(s + ":" + map.get(s));
}
Collections集合工具类
- 针对集合操作的工具类:sort,reverse,shuffle等方法