集合概述
集合是用来储存对象的、长度可变的一个容器,按照储存结构可分为两大类:单列集合Collection和双列集合Map。(本文不讲双列集合Map)。
单列集合 Collection
- 单列集合Collection接口有两个子接口:List接口和Set接口,因为都是接口,所以只能用多态的方法借助其具体实现类进行实例化。
- 常用方法:
- add(T t)添加元素至集合末尾
- remove(T t)移除指定元素
- clear()清空集合中的元素
- isEmpty()判断集合是否为空
- contains(T t)判断是否存在指定元素
- size()获取集合长度
- 迭代器Iterator(集合专用遍历方式)
- 格式:Iterator<T> 名=集合名.iterator();
- 示例:
Collection<String> c = new ArrayList<>();
Iterator<Sring> it = c.iterator();
while(it.hasNext()){
String s = it.next();//方便对取出的元素做一些操作
System.out.println(s);
}
特殊状况:并发修改异常
Iterator<String> it = l.iterator();
while(it.hasNext()){
String s = it.next();//ConcurrentModificationException 抛出并发修改异常
if(s.equals("hello"))/*预期修改值与实际修改值不一致*/
l.add("java");
}
解决方案:使用for循环
for(int i = 0;i<l.size();i++){
String s = l.get(i);//不会抛出并发修改异常
if(s.equals("hello"))
l.add("java");
}
List
- 特有方法:
- set(int i,T t)指定元素替换指定位置元素,返回被替换元素
- get(int i)得到指定索引处元素
- ArrayList:底层数据结构为数组,查询快,增删慢
- LinkedList:底层数据结构为链表,查询慢,增删快
Set
- 特点:
- 不包含重复元素
- 无包含索引的方法,不能使用用普通for循环遍历
- HashSet:
- 不包含重复元素
- 无包含索引的方法,不能使用普通for循环遍历
- 底层数据结构为哈希表
- 对集合的迭代顺序不做任何保证(即输出顺序与存入顺序不一定一致)
- LinkedHashSet:
- 底层数据结构:哈希表&链表
- 元素不可重复(由哈希表保证)
- 具有可预测的迭代顺序(输出与存入的顺序一致,由链表保证)
- TreeSet:
- 不包含重复元素
- 无包含索引的方法,不能使用普通for循环遍历
- 元素有序(按照一定规则排序,具体排序方式取决于构造方法)
- 两种构造方法:
TreeSet()根据元素的自然排序方式进行排序
TreeSet(Comparator comparator):根据指定比较器进行排序
注:哈希值与比较器详情见下文。
哈希值
- 哈希值是JDK根据对象的地址或字符串或数字算出来的int类型的数值,Object类的hasCode()方法可以获取对象的哈希值
- 同一个对象多次调用hasCode()方法得到的哈希值是相同的
- 默认情况下,不同对象的哈希值不相同(hasCode()方法重写可以使得不同对象的哈希值相同)
- 特例:字符串“重地”与字符串“通话”的哈希值相同
Comparator比较器
- 通过TreeSet集合的带参构造方法置入自定义比较器对集合元素进行排序,因为Comparator为接口,所以使用匿名内部类的方式创建其实现类对象
- 示例:
TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1,Student s2) {
int num1 = s1.getAge() - s2.getAge();
int num = num1==0?s1.getName().compareTo(s2.getName()):num1;
return num;
}
});
class Student{
private String name;
private int age;
Student() {}
Student(String name,int age) {
this.name = name;
this.age = age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
}
- 具体实例(对学生成绩进行排序):
TreeSet<Stu> ts = new TreeSet<>(new Comparator<Stu>() {
@Override
public int compare(Stu s1, Stu s2) {
int num1 = s2.getSum()-s1.getSum();
int num = num1==0?s1.getID()-s2.getID():num1;
return num;
}
});
Stu s1 = new Stu("jack",01,85,90,97);
Stu s2 = new Stu("mike",02,93,97,91);
Stu s3 = new Stu("olim",03,86,94,89);
Stu s4 = new Stu("kkkk",04,95,88,87);
Stu s5 = new Stu("tome",05,86,90,96);
Stu s6 = new Stu("lime",06,99,95,97);
Stu s7 = new Stu("lime",06,99,95,97);
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);//重复不添加
System.out.println("学号\t姓名\t语文\t数学\t英语\t总分\t排名");
int i = 1;
for(Stu s : ts) {
System.out.println(" "+s.getID()+"\t"+s.getName()+"\t"+s.getChinese()+
"\t"+s.getMath()+"\t"+s.getEnglish()+"\t"+s.getSum()+"\t "+(i++));
}
}
class Stu {
private String name;
private int ID,Chinese,Math,English,Sum;
public Stu(String name, int id, int chinese, int math, int english) {
this.name = name;
ID = id;
Chinese = chinese;
Math = math;
English = english;
Sum = chinese + math + english;
}
public int getID() {
return ID;
}
public String getName() {
return name;
}
public int getChinese() {
return Chinese;
}
public int getMath() {
return Math;
}
public int getEnglish() {
return English;
}
public int getSum() {
return Sum;
}
}