【Java】集合类
1 概述
集合是java提供的一种容器,可以存储多个数据。
集合与数组的不同:
- 数组的长度是固定的,集合的长度是可变的
- 数组存储同一类型的元素,存储基本数据类型;集合存储对象的引用,可以是不同的对象类型
2 常见集合类的继承关系
3 Collection接口
常用方法:
方法 | 功能描述 |
---|---|
public boolean add(E e) | 把给定的对象添加到当前集合中 |
public void clear() | 清空集合中所有的元素 |
public boolean remove(E e) | 把给定的对象在当前集合中删除 |
public boolean contains(E e) | 判断当前集合中是否包含给定的对象 |
public boolean isEmpty() | 判断当前集合是否为空 |
public int size() | 返回集合中元素的个数 |
public Object[] toArray() | 把集合中的元素,存储到数组中 |
3.1 Iterator迭代器
迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
Collection和Map接口主要用于存储元素,Iterator主要用于迭代访问(即遍历)Collection中的元素
常用方法:
方法 | 功能描述 |
---|---|
public Iterator iterator() | 获取集合对应的迭代器,用来遍历集合中的元素 |
public boolean add(E e) | 把给定的对象添加到当前集合中 |
public void clear() | 清空集合中所有的元素 |
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Test2_Iterator {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<String>();
coll.add("艾伦");
coll.add("三笠");
coll.add("阿尔敏");
Iterator<String> it = coll.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
当遍历集合时,首先通过调用t集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。
增强for:也称for each循环,是JDK1.5以后的高级for循环,专门用来遍历数组和集合。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
//格式:
for(元素的数据类型 变量 : Collection集合or数组){
//写操作代码
}
3.2 List接口
在List集合中的元素允许重复,所有的元素线性方式存储,在程序中可以通过索引访问集合中的指定元素。各元素的存储顺序就是插入的顺序。
常用方法:
方法 | 功能描述 |
---|---|
public void add(int index, E element) | 将指定的元素,添加到该集合中的指定位置上 |
public E get(int index) | 返回集合中指定位置的元素 |
public E remove(int index) | 移除列表中指定位置的元素, 返回的是被移除的元素 |
public E set(int index, E element) | 用指定元素替换集合中指定位置的元素,返回值是更新前的元素 |
- ArrayList集合:数据存储的结构是数据结构。元素查找快,增删慢,是最常用的集合
- LinkedList集合:数据存储的结构是链表结构。便于元素添加、删除。
3.3 Set接口
java.util.Set接口和 java.util.List 接口一样,同样继承自 Collection 接口,它与 Collection 接口中的方法基本一致,并没有对 Collection 接口进行功能上的扩充,只是比Collection 接口更加严格了。与 List 接口不同的是, Set 接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。
💎Set的构造有一个约束条件,传入的Collection对象不能有重复值
3.3.1 HashSet
java.util.HashSet 是 Set 接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。HashSet 是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于: hashCode 与 equals 方法。
在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。简单的来说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,JDK1.8引入红黑树大程度优化了HashMap的性能,那么对于我们来讲保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。
给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一:
import java.util.Objects;
public class Student {
private String name;
private int age;
public Student(){}
public Student(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o){
if(this == o){
return true;
}
if(o == null || getClass() != o.getClass()){
return false;
}
Student student = (Student) o;
return age == student.age &&
Objects.equals(name,student.name);
}
@Override
public int hashCode(){
return Objects.hash(name,age);
}
}
import java.util.HashSet;
public class HashSetDemo {
public static void main(String[] args) {
HashSet<Student> stuSet = new HashSet<Student>();
Student stu = new Student("于谦", 43);
stuSet.add(stu);
stuSet.add(new Student("郭德纲", 44));
stuSet.add(new Student("于谦", 43));
stuSet.add(new Student("郭麒麟", 23));
stuSet.add(stu);
for (Student stu2 : stuSet) {
System.out.println("name=" + stu2.getName() + ",age=" + stu2.getAge());
}
}
}
执行结果:
name=郭德纲,age=44
name=于谦,age=43
name=郭麒麟,age=23
3.3.2 LinkHashSet
要保证有序,在HashSet下面有一个子类 java.util.LinkedHashSet ,它是链表和哈希表组合的一个数据存储结构。
3.4 Collections
java.utils.Collections 是集合工具类,用来对集合进行操作。部分方法如下:
方法 | 功能描述 |
---|---|
public static |
往集合中添加一些元素 |
public static void shuffle(List<?> list) | 打乱集合顺序 |
public static |
将集合中元素按照默认规则排序 |
public static |
将集合中元素按照指定规则排序 |
4 Map集合
Collection接口定义的是单列集合。
而Map集合没有继承Collection接口,定义的是双列集合,提供Map <key,value>的映射关系,Map集合不能包含相同的键key,每个键key只能映射一个键值value。
常用子类:
- HashMap:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
- LinkedHashMap:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法
💎Map接口中的集合都有两个泛型变量,在使用时,要为两个泛型变量赋予数据类型。两个泛型变量的数据类型可以相同,也可以不同。
常用方法:
方法 | 功能描述 |
---|---|
public V put(K key, V value) | 把指定的键与指定的值添加到Map集合中 |
public V remove(Object key) | 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值 |
public V get(Object key) | 根据指定的键,在Map集合中获取对应的值 |
boolean containsKey(Object key) | 判断集合中是否包含指定的键 |
public Set |
获取Map集合中所有的键,存储到Set集合中 |
public Set<Map.Entry<K,V>> entrySet() | 获取到Map集合中所有的键值对对象的集合(Set集合) |
map的遍历1(键找值):
HashMap<String, String> map = new HashMap<String, String>();
map.put("name","bob");
map.put("age","20");
map.put("job","designer");
Set<String> keys = map.keySet();
for(String key: keys){
String value = map.get(key);
System.out.println(key + ":" + value);
}
map的遍历2(Entry键值对):
Map 中存放的是两种对象,一种称为key(键),一种称为value(值),它们在在 Map 中是一一对应关系,这一对对象又称做 Map 中的一个 Entry(项) 。Entry 将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历 Map 集合时,就可以从每一个键值对( Entry )对象中获取对应的键与对应的值。
方法:
方法 | 功能描述 |
---|---|
public K getKey() | 获取Entry对象中的键 |
public V getValue() | 获取Entry对象中的值 |
public Set<Map.Entry<K,V>> entrySet() | 获取到Map集合中所有的键值对对象的集合(Set集合) |
HashMap<String,String> map = new HashMap<String, String>();
map.put("木玛","木马乐队");
map.put("华东","重塑雕像的权利");
map.put("李剑","大波浪乐队");
Set<Map.Entry<String,String>> entrySet = map.entrySet();
for(Map.Entry<String,String> entry : entrySet){
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + ":" + value);
}