文章目录
集合
- 集合框架介绍
- 集合按照其存储结构可以分为两大类,
- 分别是单列集合java.util.Collection和双列集java.util.Map。
- 集合框架
1. Collection集合
- Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,
它有两个重要的子接口,分别是java.util.List和java.util.Set
其中,List的特点是元素有序、元素可重复。Set的特点是元素无序,而且不可重复。
List接口的主要实现类有java.util.ArrayList和java.util.LinkedList,
Set接口的主要实现类有java.util.HashSet和java.util.TreeSet。
集合中关于迭代器的实现原理:
当遍历集合时,首先通过调用集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,在调用Iterator的next()方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历迭代器的使用方法:java.util.Iterator接口:迭代器(对集合进行遍历)
- 有两个常用的方法
- .boolean hasNext() 如果仍有元素可以迭代,则返回 true
判断集合中还有没有下一元素,有的话就返回true,没有就返回false - E next() 返回迭代的下一个元素
- .boolean hasNext() 如果仍有元素可以迭代,则返回 true
1.2 关于集合中的方法:
- 学会使用API文档:
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(); 把集合中的元素,存储到数组中
1.1 List集合
java.util.List 接口继承自 Collection 接口,是单列集合的一个重要分支,习惯性地会将实现了 List 接口的对象称为List集合。在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。
- List接口特点:
1. 它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。
2. 那么集合中,元素的存储就是按照11、22、33的顺序完成的)。
3. 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
4. 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。
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) :用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
1.1.1 ArrayList集合
java.util.ArrayList 集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以 ArrayList 是最常用的集合。许多程序员开发时非常随意地使用ArrayList完成任何需求,并不严谨,这种用法是不提倡的
1.1.2 LinkedList集合
常用方法见2.1中的方法
1.2 Set接口
java.util.Set 接口和 java.util.List 接口一样,同样继承自 Collection 接口,它与 Collection 接口中的方法基本一致,并没有对 Collection 接口进行功能上的扩充,只是比 Collection 接口更加严格了。与 List 接口不同的是, Set 接口中元素无序,并且都会以某种规则保证存入的元素不出现重复
1.2.1 HashSet
- 哈希表结构图
/*
java.util.Set接口 extends Collection接口
Set接口的特点:
1.不允许存储重复的元素
2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
java.util.HashSet集合 implements Set接口
HashSet特点:
1.不允许存储重复的元素
2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
3.是一个无序的集合,存储元素和取出元素的顺序有可能不一致
4.底层是一个哈希表结构(查询的速度非常的快)
*/
public class Demo01Set {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
//使用add方法往集合中添加元素
set.add(1);
set.add(3);
set.add(2);
set.add(1);
//使用迭代器遍历set集合
Iterator<Integer> it = set.iterator();
while (it.hasNext()){
Integer n = it.next();
System.out.println(n);//1,2,3
}
//使用增强for遍历set集合
System.out.println("-----------------");
for (Integer i : set) {
System.out.println(i);
}
}
}
2. Map集合
java.util.Map<k,v>集合
- Map集合的特点:
1. Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
2. Map集合中的元素,key和value的数据类型可以相同,也可以不同
3. Map集合中的元素,key是不允许重复的,value是可以重复的
4. Map集合中的元素,key和value是一一对应 - java.util.HashMap<k,v>集合 implements Map<k,v>接口
- HashMap集合的特点:
1. HashMap集合底层是哈希表:查询的速度特别的快
- 1.1. JDK1.8之前:数组+单向链表
- 1.2. JDK1.8之后:数组+单向链表|红黑树(链表的长度超过8):提高查询的速度
2. hashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致
- HashMap集合的特点:
- java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合
LinkedHashMap的特点:- LinkedHashMap集合底层是哈希表+链表(保证迭代的顺序)
- LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的
2.1 Map接口中的常用方法
public V put(K key, V value) : 把指定的键与指定的值添加到Map集合中。
public V remove(Object key) : 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的
值。
public V get(Object key) 根据指定的键,在Map集合中获取对应的值。
public Set keySet() : 获取Map集合中所有的键,存储到Set集合中。
public Set<Map.Entry<K,V>> entrySet() : 获取到Map集合中所有的键值对对象的集合(Set集合)
2.2 Map集合遍历键找值方式
2.2.1 Map集合的第一种遍历方式:通过键找值的方式
- Map集合中的方法:
- Set keySet() 返回此映射中包含的键的 Set 视图。
- 实现步骤:
1. 使用Map集合中的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中
2. 遍历set集合,获取Map集合中的每一个key
3. 通过Map集合中的方法get(key),通过key找到value
代码的实现
public class MapKeySetDemo01 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("赵丽颖",168);
map.put("杨幂",163);
map.put("刘亦菲",169);
// 1.使用Map集合中的方法KeySet(),把Map集合中的所有Key取出来,存储到一个set集合中去
Set<String> set = map.keySet();
// 2.遍历set集合,获取Map集合中的每一个Key
// 可以通过迭代器的方法是进行遍历
Iterator<String> it = set.iterator();
while(it.hasNext()){
String key = it.next();
// 3.通过Map集合中的方法get(Key),在通过Key找到value
Integer value = map.get(key);
System.out.println(key+" "+value);
}
}
}
2.2.2 Map集合遍历的第二种方式:使用Entry对象遍历
- MAp集合中的方法:
Set<Map.Entry<K,V>> entrySet()返回此映射中包含的映射关系的 Set 视图。 - 实现步骤:
1. 使用Map集合中的方法entrySet(),把Map集合中对各Entry对象取出来,存储到一个Set集合中
2. 遍历Set集合,获取每一个Entry对象
3. 使用Entry对象中的方法getKey和getValue获取键与值
实现代码
public class MapKeySetDemo02 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("张三",168);
map.put("赵四",163);
map.put("刘五",169);
// 1.使用Map集合中的方法entrySet(),把Map集合中对各Entry对象取出来,存储到一个Set集合中
Set<Map.Entry<String, Integer>> set = map.entrySet();
// 2.遍历Set集合,获取每一个Entry对象
Iterator<Map.Entry<String, Integer>> it = set.iterator();
while(it.hasNext()){
Map.Entry<String, Integer> entry = it.next();
// 3.使用Entry对象中的方法getKey和getValue获取键与值
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+" "+value);
}
}
}
2.3 LinkedHashMap、HashMap
-
HasMap存取自定义类型键值
- Key:Person类型
- Person类就必须重写hashCode方法和equals方法,以保证key唯一Value:String类型 可以重复
-
HashMap与Hashtable的不同之处
- HashMap集合(包括之前所学的所有的集合),都是可以存取null值,null键
- Hashtable集合,不能存储null值,也不能存储null键,否则会发生异常
2.3.1 LinkedHashMap
java.util.LinkedHashMap<K,V>Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。此
实现与 HashMap 的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。
底层原理:
哈希表+链表(记录元素的顺序)
public class LinkedHashMapDemo01 {
public static void main(String[] args) {
show02();
}
private static void show02() {
LinkedHashMap<String,String> linked = new LinkedHashMap<>();
linked.put("a","红楼梦");
linked.put("c","三国演义");
linked.put("b","水浒传");
linked.put("a","西游记");
System.out.println(linked); //对应的Key值不可以重复(若有重复,则会发生替代),LinkedHashMap是有序排列
//输出结果 {a=西游记, c=三国演义, b=水浒传}
}
private static void show01() {
HashMap<String,String> map = new HashMap<>();
map.put("a","红楼梦");
map.put("c","三国演义");
map.put("b","水浒传");
map.put("a","西游记");
System.out.println(map); //对应的Key值不可以重复(若有重复,则会发生替代),HashMap是无序排列
//输出结果 {a=西游记, b=水浒传, c=三国演义}
}
}
2.3.2 HashMap
- HasMap存取自定义类型键值
- Key:Person类型
- Person类就必须重写hashCode方法和equals方法,以保证key唯一
- Value:String类型
- 可以重复
- Key:Person类型
HashMap与Hashtable的不同之处
HashMap集合(包括之前所学的所有的集合),都是可以存取null值,null键
Hashtable集合,不能存储null值,也不能存储null键,否则会发生异常
public class HasMapSavePersonDemo01 {
public static void main(String[] args) {
// show01();
show02();
}
private static void show02() {
HashMap<Person,String> map = new HashMap<>();
map.put(new Person("女王",18),"英国");
map.put(new Person("普金",32),"俄罗斯");
map.put(new Person("秦始皇",23),"秦朝");
map.put(new Person("女王",18),"毛里求斯");
//使用EntrySet集合和增强for循环
Set<Map.Entry<Person, String>> set = map.entrySet();
for(Map.Entry<Person,String> entry:set){
Person key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"---->"+value);
/* 若不在Person类中重写hashCode方法和equals方法
则输出的值为 Person{name='秦始皇', age=23}---->秦朝
Person{name='普金', age=32}---->俄罗斯
Person{name='女王', age=18}---->毛里求斯
Person{name='女王', age=18}---->英国
若在Person类中重写hashCode方法和equals方法
则输出的值为 Person{name='女王', age=18}---->毛里求斯
Person{name='普金', age=32}---->俄罗斯
Person{name='秦始皇', age=23}---->秦朝
* */
}
}
private static void show01() {
HashMap<String,Person> map = new HashMap<>();
map.put("北京",new Person("张三",18));
map.put("上海",new Person("李四",19));
map.put("深圳",new Person("赵六",17));
map.put("北京",new Person("小华",16));
Set<String> set = map.keySet();
//使用迭代器的Iterator()方法对Set集合进行遍历
/*Iterator<String> it = set.iterator();
while(it.hasNext()){
String key = it.next();
Person value = map.get(key);
System.out.println(key+"--->"+value);
}*/
//使用Foreach增强循环对Set集合进行遍历
for(String key:set){
Person value = map.get(key);
System.out.println(key+"--->"+value);
}
}
}