一、集合的概念
集合:JDK中提供了一系列特殊的类,这些类可以存储任意类型的对象,并且长度可变,在java中这些类统称为集合。
二、集合的分类
集合按照存储结构可以分为两大类:单列结合Collection和双列集合Map。
Collection:单列集合类的根接口,他有两个重要的子接口List和Set。List的特点是:元素有序、可重复。List接口的主要实现类有:ArrayList、LinkedList。Set的特点是元素无序、不可重复。Set接口的主要实现类有:HashSet、TreeSet。
Map:双列集合类的根接口,用于存储具有键(key)、值(Value)映射关系的元素,可以通过指定的key找到对应的value。Map接口的主要实现类有:HashMap、TreeMap。
三、List
在程序中可以通过索引来访问集合中的指定元素。元素的存入顺序和取出顺序一致。
(1)ArrayList集合
通过程序说明ArrayList集合的增删改查
由于ArrayList集合的底层是使用一个数组来保存元素的,在增加或删除指定位置的元素时,会导致创建新的数组,效率比较低,因此不适合做大量的增删操作。但这种数组的结构允许通过索引的方式来访问元素,因此查找元素比较便捷。
public class Test {
public static void main(String[] args) {
List l=new ArrayList();
l.add(1); //增
l.add("a");
System.out.println(l.size());
System.out.println(l);
String s1=(String) l.get(1); //查
System.out.println(s1);
l.set(0, 0); //改
l.set(1, 0);
System.out.println(l);
l.remove(0); //删
System.out.println(l);
}
}
(2)LinkedList集合
该集合内部维护了一个双向循环链表,链表中的每一个元素都使用引用的方式来记住它的前一个元素和后一个元素。当插入或删除一个元素时,只需要修改元素之间的这种引用关系即可。因此LinkedList集合对于增删具有很高的效率。
四、Set
Set接口中元素无序、元素不重复
(1)HashSet
当向HashSet集合中添加一个对象时,,首先会调用该对象的hashCode()方法来计算对象的哈希值,从而确定元素的存储位置。
HashSet集合不出现重复元素的原因:当存入对象时,首先调用当前存入对象的hashCode()方法获得对象的哈希值,然后根据对象的哈希值计算出一个存储位置。如果该位置上没有元素,则直接将元素存入,如果该位置上有元素存在,则会调用equals()方法让当前存入的元素依次和该位置上的元素比较,如果返回的结果为false就将该元素存入。
为保证HashSet正常工作,要求在存入对象时,重写Object类中的hashCode()方法和equals()方法。String类已经重写了hashCode()方法和equals()方法。
class Student{
private int id;
private String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return id+":"+name;
}
//重写hashCode()方法,根据id确定存储位置。
@Override
public int hashCode() {
return id;
}
//重写equals()方法
@Override
public boolean equals(Object obj) {
if(this==obj) {//判断是否是同一个对象
return true;
}
if(obj instanceof Student) {//判断对象是不是Student类型
Student stu=(Student)obj;
return stu.id==this.id&&stu.name.equals(this.name);
}
return false;
}
}
public class Test {
public static void main(String[] args) {
HashSet set=new HashSet();
//先存取三个对象
set.add(new Student(1, "张三"));
set.add(new Student(2, "李四"));
set.add(new Student(3, "王五"));
//添加id为1,name为李四的对象
//根据重写的hashCode()方法得出存储位置,该位置上有元素
//然后调用重写的equals()方法,比较当前元素和该位置上的元素
//两个元素不相等,所以可以存入集合中。
set.add(new Student(1, "李四"));
//当前元素与该位置上的元素相同,不能存入。
set.add(new Student(1, "张三"));
System.out.println(set);
}
}
五、Map
Map接口是一种双列集合,它的每个元素都包含一个键对象Key和一个值对象Value,键和值之间存在一种对应关系,称为映射。
(1)HashMap
①Map中的键是唯一的,如果存取了相同的键,后存储的值会覆盖原有的值。
public class Test {
public static void main(String[] args) {
HashMap map=new HashMap();
//先存取三个对象
map.put(1, "ROSE");
map.put(2, "Jack");
map.put(3, "Mary");
System.out.println(map);
//继续添加一个Key为1,Value为Lucy的元素.
//已经存在相同的Key了,所以Lucy会替代ROSE
map.put(1, "Lucy");
System.out.println(map);
}
}
②遍历HashMap
<1>第一种方式:先遍历Map集合中的所有键,再根据键获取相应的值
public class Test {
public static void main(String[] args) {
HashMap map=new HashMap();
map.put(1, "ROSE");
map.put(2, "Jack");
map.put(3, "Mary");
Set keySet=map.keySet();//获取键的集合
Iterator it=keySet.iterator();//迭代键的集合
while(it.hasNext()) {
Object obj1=it.next();
Object obj2=map.get(obj1);
System.out.println(obj1+":"+obj2);
}
}
}
<2>第二种方式:先获取集合中的所有映射关系,然后从映射关系中取出键和值。先获取Map中所有映射的Set集合,集合中是Map.Entry类型的元素(Entry是Map的内部类),就是键值对。
public class Test {
public static void main(String[] args) {
Map map=new HashMap();
map.put(1, "Rose");
map.put(2, "Jack");
map.put(3, "Lucy");
Set entrySet=map.entrySet();//获取映射关系的Set集合
Iterator it=entrySet.iterator();
while(it.hasNext()){
Map.Entry entry=(Map.Entry)it.next();//获取映射关系集合中的每个元素,即键值对
Object key=entry.getKey();
Object value=entry.getValue();
System.out.println(key+":"+value);
}
}
}
<3>第三种方式:通过Map的values()方法,获取值得Collection集合,然后遍历Collection集合中的元素
public class Test {
public static void main(String[] args) {
Map map=new HashMap();
map.put(1, "Jack");
map.put(2, "Rose");
map.put(3, "Lucy");
Collection cl=map.values();//获取Map集合中值得Collection集合
Iterator it=cl.iterator();
while(it.hasNext()){
Object obj=it.next();
System.out.println(obj);
}
}
}
(2)LinkedHashMap
HashMap集合迭代出来的元素顺序与存入的顺序不一致。HashMap有一个子类LinkedHashMap,LinkedHashMap中像LinkedList一样使用双向链表维护内部元素的关系,使Map元素的迭代顺序与存入顺序一致。