一.Collection三种遍历方式
(1)普通for 平时写的for(i=0;i<n;i++)一样
(2)增强for 用来遍历数组,数组类型为什么,遍历类型就为什么
例如:
for(Student s : list) {
System.out.println(s.getName()+","+s.getAge());}
(3)迭代器方法遍历
hasNext()如果迭代具有更多元素,返回true
next()返回迭代中的下一个元素
通过集合对象,获取迭代器对象
例如:
//集合对象
Collection<Student> c = new ArrayList<Student>();
//迭代器对象
Iterator<Student> it = list.iterator();
//迭代器方式
while(it.hasNext()) {
Student s = it.next();
System.out.println(s.getName()+","+s.getAge());
}
(4)常用方法
add() 添加,clear()清空,remove()从集合中移除指定元素,isEmpty()判断集合是否为空
二.List集合概述和特点
特点
(1)有序集合(也称为序列),可以精确控制列表中每个元素的插入位置,可以通过索引访问元素,并搜索列表中的元素。
(2)与Set集合不同,允许重复元素
(3)有序:存储和取出的元素顺序一致
常用子类 :
Arraylist(查询快,增删慢),linkedlist(查询慢,增删快);
Arraylist 底层数据结构为数组
linkedlist底层数据结构为链表
并发修改异常(迭代器使用问题)
按照Collection的迭代器方法会出现的异常
modCount:实际修改集合次数
expectedModCount:预期修改集合次数
调用next方法时,都会判断两者是否一致,不能一边遍历时,一边添加元素(modCount增加,但是expectedModCount未增加)
解决:
(1)通过for循环用get方法获取元素
(2)listIterator列表迭代器
next方法使用时,modCount的值会赋值给expectedModCount;
通过List集合的listIterator()方法得到,List集合特有的迭代器
可以按照任意方向遍历,并且可以边遍历,边添加元素
hasNext()向前遍历,hasPrevious()相反方向遍历,next()下一个元素并向前移动光标,previous()上一个元素,并向后移动光标。
补充:刚开始可能不能从后遍历,因为光标在最前面,无法从后往前遍历,要先从前往后遍历一次可能才能成功。(代码第一次从后遍历失败,仅猜测)
linkedlist基本方法
getFirst()返回第一个元素,getLast()返回最后一个removeFirst()删除第一个,removeLast()删除最后一个。
三.Set集合概述和特点
特点
(1)不包含重复元素的集合
(2)没有带索引的方法,所以不能使用for循环遍历
实现类
HsahSet集合概述和特点
实现Set接口,对迭代顺序没有保证,不能在一段时间保持不边(就是输入顺序和顺出顺序可能对不上)
哈希值
JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
hashCode()可以返回对象的哈希码值
同一个对象多次调用hashCode的哈希值是相同的
即使对象的内容相同,哈希值也不同
例如:
public class HashDemo {
/*
* 哈希值是jdk根据对象的地址或字符串过着数字算出来的int类型的数值
* hashCode()返回对象的哈希码值
*/
public static void main(String[] args) {
// TODO 自动生成的方法存根Student s1 = new Student("林青霞",30);
System.out.println(s1.hashCode());
System.out.println(s1.hashCode());
//同一个对象多次调用hashCode的哈希值是相同的
Student s2 = new Student("林青霞",30);
System.out.println(s2.hashCode());
//默认情况下(Object中的hashCode),不同对象的哈希值是不同的,重写hashCode
//通过重写hashCode可以实现不同对象哈希值是相同的
System.out.println("重地".hashCode());
System.out.println("通话".hashCode());
//字符串重写hashCode方法,这两个很特别
}}
对象类中重写hashCode和equals方法,直接生成即可
@Override
public int hashCode() {
return Objects.hash(age, name);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
return age == other.age && Objects.equals(name, other.name);
}
HashSet集合概括和特点
(1)底层数据结构是哈希表
(2)对集合的迭代顺序不作任何保证
(3)没有带索引的方法,所以不能使用for循环遍历
(4)由于是Set集合,所以不包含重复元素的集合
HashSet集合保证元素唯一性,添加一个元素的过程
HashSet存储元素时:
要保证唯一性,需要重写hashCode和equals
LinkedHashSet集合概述和特点
(1)哈希表和链表实现的Set接口,具有可预测的迭代次序
(2)由链表保证元素有序(就是输入顺序和输出顺序一样)
(3)由哈希表保证元素唯一(也就是没有重复元素)
TreeSet集合概述和特点
间接实现Set,基本类型要使用引用类型,会自动装箱,拆箱
(1)元素有序:不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决与构造方法
TreeSet():根据其元素的自然排序进行排序(从小到大)
TreeSet(Comparator comparator):根据指定的比较器进行排序
(2)没有带索引的方法,所以不能使用普通for循环遍历
(3)由于是Set集合,没有重复元素
自然排序Co'm'pa'rable的使用
(1)用TreeSet集合存储自定义对象无参构造方法是自然排序对元素进行排序的
(2)元素所属的类要实现Co'm'pa'rable接口,重写co'm'pa'reTo(T o)方法
(3)重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
TreeSet<Integer> ts = new TreeSet<Integer>();
public int compareTo(Student s) {
//return 0 相同
//return 1 (正数)升序
//return -1(负数) 降序
//按照年龄从小到大排序
int num = this.age-s.age;//this 相当于s2,s相当于s1
//升序this再前,降序this在后
int num2 = num==0?this.name.compareTo(s.name):num;
return num2;
}
带参构造方法,指定比较器
(1)用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
(2)比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T O2)方法
(3)重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {//就是个内部类 @Override public int compare(Student s1, Student s2) { //int num = (s2.getChinese()+s2.getMath())-(s1.getChinese()+s1.getMath()) //主要条件 int num = s2.getSum() - s1.getSum(); //次要条件 int num2 = num==0?s1.getChinese()-s2.getChinese():num; int num3 = num2==0?s1.getName().compareTo(s2.getName()):num2; return num3; } });