集合基础知识
1. List接口
1.1 简介
信息 | 内容 |
---|---|
接口包名 | java.util.List |
继承关系 | Collection 接口 |
特点简介 | 带索引、允许重复、元素有序 |
1.2 常用方法
void add(int index, E element)
将元素添加到指定位置上E get(int index)
返回集合中指定,位置的元素E remove(int index)
移除列表中指定位置的元素, 返回被移除的元素E set(int index, E element)
用指定元素替换集合中指定位置的元素,返回更新前的元素
注意事项:集合索引不要越界,否则会出现IndexOutOfBoundsException(RuntimeException)
1.3 List接口的实现类
1.3.1 ArrayList集合
简介
java.util.ArrayList
可变的数组的实现,存储在内的数据称为元素,此类提供一些方法来操作内部存储的元素
构造方法
public ArrayList()
构造一个内容为空的集合
ArrayList<String> list = new ArrayList<>();
成员方法
boolean add(E e)
将e添加到此集合的尾部,返回是否添加成功boolean add(E e)
将e添加到此集合的尾部,返回是否添加成功E remove(int index)
移除此集合中index上的元素,返回被删除的元素E get(int index)
返回此集合中index上的元素int size()
返回此集合中的元素数,一般用于遍历
1.3.2 LinkedList集合
简介
java.util.LinkedList
- 底层是链表结构:查询慢增删快
- 包含了大量操作首尾元素的方法
- 使用特有方法(下列常用方法)时不能使用多态
常用方法
void addFirst(E e)
将指定元素插入此列表的开头void addLast(E e)
将指定元素添加到此列表的结尾void push(E e)
将元素推入此列表所表示的堆栈(等效于addFirst)E getFirst()
返回此列表的第一个元素E getLast()
返回此列表的最后一个元素E removeFirst()
移除并返回此列表的第一个元素E removeLast()
移除并返回此列表的最后一个元素E pop()
从此列表所表示的堆栈处弹出一个元素(等效于removeFirst)boolean isEmpty()
如果列表不包含元素,则返回true
2. Set接口
2.1 简介
信息 | 内容 |
---|---|
接口包名 | java.util.Set |
继承关系 | Collection 接口 |
特点简介 | 不带索引、不允许重复、元素无序 |
常用取出元素的方式:迭代器、增强for循环
2.2 Set接口的实现类
2.2.1 HashSet集合
简介
java.util.HashSet
-
不可重复
-
不包含索引,不能使用普通for循环遍历
-
无法保证迭代顺序(元素是混乱的)
保证元素唯一性:依赖于hashCode与equals方法,元素必须重写hashCode和equals方法保证相同hash下可比较元素内容是否相同
-
底层是Hash表(查询速度快)
存储自定义类型的数据
为保证元素唯一,需要重写HashCode和equals方法
以下是IDEA自动生成的equals和HashCode方法
@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);
}
2.2.2 LinkedHashSet集合
java.util.LinkedHashSet
底层实现:哈希表 + 链表 / 红黑树 + 链表(记录元素存储顺序)
3. Collection集合
3.1 简介
- 单列集合类的根接口,用于存储一系列符合某种规则的元素
- 它有两个重要的子接口,分别是
java.util.List
和java.util.Set
3.2 常用方法
Collection 是所有单列集合的父接口,因此在 Collection 中定义了单列集合(List 和 Set)通用的一些方法,这些方法可用于操作所有的单列集合
-
boolean add(E e)
把给定的对象添加到当前集合中 -
void clear()
清空所有元素 -
boolean remove(E e)
把给定的对象从集合中删除,返回是否存在e -
boolean contains(E e)
判断当前集合是否包含给定对象,返回是否存在e -
boolean isEmpty()
判断当前集合是否为空 -
int size()
返回集合中元素的个数 -
Object[] toArray()
把集合中的元素存入数组中-
可在
toArray
括号中添加 new 数组使其返回填写类型的数组public class CollectionDemo { Collection<String> collection = new ArrayList<>(); collection.add("张三"); collection.add("李四"); collection.add("王五"); String[] strings = collection.toArray(new String[collection.size()]); System.out.println(Arrays.toString(strings)); }
-
3.3 迭代器
在程序开发中,经常需要遍历集合中的所有元素,针对这种需求,JDK专门提供了一个接口 java.util.Iterator
3.3.1 迭代的定义
在取元素之前先判断集合中有没有元素,如果有,就把这个元素取出来,再判断如果还有就再取出来,直到把集合中的所有元素取出,这种取出方式称为迭代
3.3.2 Iterator
的使用
获取迭代器
由于实现了 Collection
接口的实现类均实现了 Iterator
接口,因此具有如下通用方法
public Iterator iterator()
获取集合对应的迭代器
常用方法
public E next()
返回迭代的下一个元素public boolean hasNext()
如果仍有元素可以迭代,则返回 true
public class iteratorDemo{
Collection<String> strings = new ArrayList<>();
strings.add("ABC");
strings.add("123");
Iterator<String> iterator = strings.iterator();
while(iterator.hasNext()){
String str = iterator.next();
System.out.println(str);
}
}
3.3.3 增强for循环
增强for循环(foreach)是JDK1.5以后出来的一个高级for循环,用来专门遍历数组和集合,本质为迭代器
使用格式
for(元素的数据类型 变量 : 待遍历内容){...}
注意事项:这里的待遍历内容仅可为集合或数组
// 使用增强for遍历数组
public class Demo01 {
public static void main(String[] args) {
int[] arr = {3,5,6,87};
for(int num : arr){
System.out.println(num);
}
}
}
// 使用增强for遍历集合
public class Demo02 {
public static void main(String[] args) {
Collection<String> strings = new ArrayList<>();
strings.add("ABC");
strings.add("123");
for(String str : strings){
System.out.println(str);
}
}
}
4. Collections工具类
java.util.Collections
4.1 可变参数
可变参数的底层为数组,遍历时可以使用增强for循环
定义格式
修饰符 返回值类型 方法名(参数类型... 形参名){ }
public void MethodName(Object... obj){ }
public static int getSum(int... arr) {
int sum = 0;
for (int a : arr) {
sum += a;
}
return sum;
}
注意事项
- 一个参数列表中只能具有一个可变参数
- 若具有多个参数,可变参数必须位于参数列表的结尾
4.2 常用方法
-
static <T> boolean addAll(Collection<T> c, T... elements)
向集合中添加多个元素 -
static void shuffle(List<?> list)
打乱集合原先顺序 -
static <T> void sort(List<T> list)
将集合中的元素进行升序排序 -
static <T> void sort(List<T> list,Comparator<? super T> )
将集合中元素按照指定规则排序使用前提:被排序的元素的类必须实现Comparable接口,重写接口中的方法
compareTo(T o)
,即自定义定义排序的规则
4.3 Comparable接口
简介
我们可以使用sort方法进行String类型的默认排序,是因为String类实现了Comparable接口,同时重写了compareTo(T o)
方法实现了该接口的实现类可以进行Collections.sort
或Arrays.sort
自动排序
compareTo
方法
排序规则
对于数值型而言,其余可依据此推导
- 升序:this(自己)— 参数
- 降序:参数 — this(自己)
@Override
public int compareTo(Person person) {
return this.getAge() - person.getAge();
}
4.4 Comparator接口
Comparator 这个接口,位于 java.util
包下,排序是 Comparator 能实现的功能之一,需要实现该接口中的 compare 方法
compare
方法
public int compare(T o1, T o2)
使用o1与o2自定义定义排序的规则
使用方法
两个对象比较的结果有三种:大于,等于,小于
- 按照升序排序:
o1
小于o2
,返回负数,相等返回0,o1
大于o2
返回正数 - 按照降序排序:
o1
小于o2
,返回正数,相等返回0,o1
大于o2
返回负数
5. Map接口
5.1 简介
信息 | 内容 |
---|---|
接口包名 | java.util.Map |
继承关系 | Collection 接口 |
特点简介
- Map是一个双列集合,一个元素包含两个值
- Map集合中的元素,Key 和 Value 的值不一定相同
- Key 不允许重复,Value 允许重复
- Key 和 Value 一一对应
5.2 Map接口的实现类
- HashMap<K,V>
- 存储数据采用的哈希表结构,元素的存取顺序不一定一致
- 由于键不能重复,需要重写键的
hashCode()
方法、equals()
方法
- LinkedHashMap<K,V>
- HashMap下的子类LinkedHashMap
- 存储数据采用的哈希表结构 + 链表结构,通过链表结构保证元素的存取顺序一致
- 由于键不能重复,需要重写键的
hashCode()
方法、equals()
方法
5.3 Map接口常用方法
-
V put(K key, V value)
把指定的Key与指定的Value添加到Map集合中若键在集合中没有,返回
null
并把指定的键值添加到集合中,若存在,则返回值该值为替换前的值,并把指定键所对应的值,替换成指定的新值 -
V remove(Object key)
把包含指定Key元素在Map集合中删除,返回被删除元素的Value -
V get(Object key)
根据指定的Key,在Map集合中获取对应的Value -
boolean containsKey(Object key)
判断集合中是否包含指定的Key -
Set<K> keySet()
获取Map集合中所有的Key,存储到Set集合中,返回Set集合 -
Set<Map.Entry<K,V>> entrySet()
获取到Map集合中所有的Key/Value对对象的集合(Set集合)
5.4 Map集合的遍历
5.4.1 增强for循环
- 获取Map中所有的键,使用
keySet()
- 遍历键的Set集合,得到每一个键
- 根据键,获取键所对应的值使用
get(K key)
public class MapDemo {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<String,String>();
map.put("A", "1");
map.put("B", "2");
map.put("C", "3");
Set<String> Keys = map.keySet();
for (String Key : Keys) {
String Value = map.get(Key);
System.out.println(Key + Value);
}
}
}
5.4.2 Entry 键值对
简介
Entry 将键值对的对应关系封装成了对象,这样我们在遍历 Map 集合时,就可以从每一个键值对对象中获取对应的键与对应的值
常用方法
public K getKey()
获取 Entry 对象中的 Keypublic V getValue()
获取 Entry 对象中的 Value
使用方法
- 获取Map集合中所有的 Entry 对象,使用
entrySet()
- 历包含 Entry 对象的Set集合,得到每一个 Entry 对象
- 获取 Entry 对象中的键与值,使用
getkey()
和getValue()
方法
public class MapDemo {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<String,String>();
map.put("A", "1");
map.put("B", "2");
map.put("C", "3");
Set<Entry<String,String>> entrySet = map.entrySet();
for (Entry<String,String> entry : entrySet) {
System.out.println(entry.getKey() + entry.getValue());
}
}
}
Map 集合不能直接使用迭代器或增强 for 循环进行遍历,但是转成 Set 之后就可以使用了
5.5 存储自定义类型键值
要求 创建一个学生类并定义多个学生对象,将学生对象及其所对应的地址存储至Map集合中
public class Student {
private String name;
private int age;
}
分析 由于Map集合中不允许存储相同的Key,故需在Student类中重写equals及hashCode方法
@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);
}
总结
- 使用HashMap中存放自定义对象时,必须复写对象的hashCode和equals方法
- 使用
java.util.LinkedHashMap
集合可以保证Map中存放的Key和取出的顺序一致
5.6 JDK9+对集合添加的优化
我们在代码中创建一个集合并直接用一些元素填充它,n 多个 add 或 put 方法的书写使得代码重复, Java9 之后添加了 of 静态方法,以便更好创建不可改变的实例
public class DemoMethod {
public static void main(String[] args) {
Set<String> set = Set.of("a","b","c");
System.out.println(set1);
Map<String,Integer> map = Map.of("a",1,"b",2);
System.out.println(map);
List<String> list = List.of("a","b");
System.out.println(list);
}
}
注意事项
-
of 方法只是 Map、List、Set 这三个接口的静态方法,比如 HashSet、ArrayList 等中没有该方法,故需使用多态才可使用 of 方法
-
返回的集合是不可变的,不可使用 add 或 put 方法再添加元素