java集合框架:List/Set 接口和其子类
目录
1. List接口
-
java.util.List接口 extends Collecton接口 -
特点:
- 有序的集合
- 有索引,包含了一些带索引的方法
- 允许存储重复的元素
-
带索引的方法(特有)(注意防止索引越界异常)
public void add(int index ,E element):将元素添加到指定位置。public E get(int index):返回集合中指定位置的元素public E remove (int index):移除列表中指定的元素,返回的是被移除的元素public E set (int index , E element):用指定元素替换集合中指定位置的元素,返回值为更新前的元素。
public class Demo01 {
public static void main(String[] args) {
//使用多态创建一个集合对象
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("a");
System.out.println(list);//[a, b, c, d, a] 重写了toString()方法
// public void add(int index ,E element):将元素添加到指定位置。
list.add(3,"new3");
System.out.println(list);//[a, b, c, new3, d, a]
//remove()
System.out.println("被移除的元素:"+list.remove(2));//被移除的元素:c
System.out.println(list);//[a, b, new3, d, a]
//set()
System.out.println("被替换的元素:"+list.set(4,"A"));//被替换的元素:a
System.out.println(list);//[a, b, new3, d, A]
//遍历三种方式:
// 1.普通for循环
for (int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
// 2.使用迭代器
Iterator<String> it=list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//增强for
for (String s:list){
System.out.println(s);
}
}
}
2. List的子类
ArrayList
java.util.ArrayList集合数据存储的结构是数组结构- 增删慢、查找快
- 此实现不是同步的
LinkedList集合
java.util.LinkedList集合数据存储的结构是链表结构- 查询慢、增删快
- 是一个双向链表:有大量对首位操作的方法
- 使用特有的方法,不能使用多态
- 此实现不是同步的
Vector
Vector底层也是数组,是同步的,速度慢;- 从Java 2平台v1.2,这个类被改造为实现List接口,可以使用List接口里的方法
- 如果不需要线程安全的实现,建议使用ArrayList代替Vector
3. Set接口
- 不包含重复元素的集合
- 没有索引,没有带索引的方法,不能使用普通的for循环遍历
HashSet
- 此类实现Set接口,由哈希表(实际为HashMap实例)支持。
- 是个无序集合:对集合的迭代顺序不作任何保证; 特别是,它不能保证该顺序恒久不变。
- 允许null元素。
- 此实现不是同步的
哈希值
-
是一个十进制的整数,由系统随机给出(就是对象的地址,是一个逻辑地址,是模拟出来得到的地址,不是数据实际存储的物理地址)
-
在Object类有一个方法,可以获取对象的哈希值:
int hashCode()//hashCode方法的源码: public native int hashCode(); //native:代表该方法调用的是本地操作系统的方法 //toString方法源码:也用了hashCode方法,输出的逻辑地址是一样的 public String toString(){ return getClass().getName()+"@"+Integer.toHexString(hashCode()); } -
String类的哈希值:String类重写了Object类的hashCode方法
String s1=new String("abc"); String s2=new String("abc"); System.out.println(s1.hashCode());//96354 System.out.println(s2.hashCode());//96354 -
两个元素不同,但是哈希值相同:哈希冲突
System.out.println("重地".hashCode());//1179395 System.out.println("通话".hashCode());//1179395
HashSet集合存储数据的结构:哈希表
-
jdk1.8之前:哈希表=数组+链表
-
jdk1.8之后:哈希表=数组+链表;哈希表=数组+红黑树(提高查询的速度)
-
哈希表的特点:速度快
-
数组结构:把元素进行了分组(相同哈希值的元素是一组),链表/红黑树结构把相同哈希值的元素连接到一起
存储数据到集合中时:先计算元素的哈希值

如果链表的长度超过了8位,那么就会把链表转换为红黑树
HashSet存储自定义类型元素
-
Set集合不允许重复元素的原理
- Set集合在调用add方法时,回调用元素的hashCode方法和equals方法判断元素是否重复
-
HashSet存放自定义类型元素时,需要重写对象中的
hashCode()和equals()方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一
//例:要求:同名同年龄的人只能存储一次
public class Person {
private String name;
private int age;
//重写equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
//重写hashCode方法
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//测试类
public class Demo01 {
public static void main(String[] args) {
HashSet<Person> set=new HashSet<>();
Person p1=new Person("aa",20);
Person p2=new Person("bb",22);
Person p3=new Person("aa",20);
System.out.println(p1.hashCode());//97205
System.out.println(p2.hashCode());//98199
System.out.println(p3.hashCode());//97205
System.out.println(p1==p3);//false
System.out.println(p1.equals(p3));//true
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(set);//[Person{name='aa', age=20}, Person{name='bb', age=22}]
}
}
LinkedHashSet
- HashSet下有一个子类
java.util.LinkedHashSet,是链表和哈希表组合的一个数据存储结构; - 此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表,多了一条链表用来记录元素的存储顺序,保证元素有序

浙公网安备 33010602011771号