容器最基本的操作规律。
集合(容器)的操作规律: CRUD create read update delete
集合类型
集合按照其存储结构可以分为两大类,分别是:
//1.单列集合java.util.Collection
//2.双列集合java.util.Map
Collection:包含了List,Set子接口
一、List的特点是元素有序、元素可重复。底层维护的是数组。每个元素都有对应的下标。它下面的两个重要实现类:
//1.java.util.ArrayList
//2.java.util.LinkedList
二、Set的特点是元素无序,而且元素不可重复。它下面的两个重要实现类:
//1.java.util.HashSet
//2.java.util.TreeSet
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(): 把集合中的元素,存储到数组中。
2.2 迭代器
//重要知识点:
Iterator<String> it = coll.iterator();
while( it.hasNext() ) {
// 取出数据
String next = it.next();
// 判断取出的数据是否为abc
if( next.equals("abc") ) {
it.remove();
}
}
当我们在使用迭代器对集合中的元素进行迭代时,不允许使用集合中自带的
增删方法对集合中的元素进行操作。因为集合基于iterator获取一个迭代器
此时这个迭代器是针对集合中的元素而获取的,如果此时用集合自身的方法进行
增删擦操作那么集合中的元素就会发生变化。
导致在获取迭代器之前和正在迭代的元素不一样,所以不允许这么干。
*/
// coll.remove(next); // 报错
// 在使用迭代器遍历集合时,只能使用迭代器中的方法删除集合中的数据
注意
1、使用迭代器对集合进行迭代的时候,不要使用集合自身的功能对集合进行增删操作。
2、所有的迭代器当迭代结束之后,那么这个迭代器就位于集合的最后。无法再进行迭代,所以一般针对于集合的迭代使用for循环。
3、使用迭代器迭代集合的时候,每一个hasNext方法都对应一个next,不要一个hasNext方法对应多个next。
2.3 增强for
专门用来遍历数组和集合的。
一、List: 有下标,方法都是通过下标操作的。可以保存重复元素,可以保证元素的存取顺序。 遍历可以通过普通for循环。
1.ArrayList: 底层是数组。特有方法都是围绕下标操作的。
2.LinkedList:底层是链表。特有方法都是围绕头和尾操作。
ArrayList
许多程序员开发时非常随意地使用ArrayList完成任何需求,并不严谨,这种用法是不提倡的。
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) :用指定元素替换集合中指定位置的元素,返回值的更新前的元素
LinkedList常用方法
- public void addFirst(E e):将指定元素插入此列表的开头。
- public void addLast(E e):将指定元素添加到此列表的结尾。
- public E getFirst():返回此列表的第一个元素。
- public E getLast():返回此列表的最后一个元素。
- public E removeFirst():移除并返回此列表的第一个元素。
- public E removeLast():移除并返回此列表的最后一个元素。
- public E pop():从此列表所表示的堆栈处弹出一个元素。
- public void push(E e):将元素推入此列表所表示的堆栈。
- public boolean isEmpty():如果列表不包含元素,则返回true
二、Set: 无下标,方法都是从Collection父接口中继承,没有特有方法。 不能保存重复元素,不保证元素的存取顺序。
1.HashSet:底层是哈希表结构。不能保存重复元素,不保证元素的存取顺序。 依赖于hashCode()方法 和 equals()方法。
哈希表:哈希值 + 数组 + 链表(红黑树)。
1.对象调用hashCode()方法,计算出自己在数组中的位置。
2.当出现了哈希冲突,则调用equals()方法,比价两个对象是否相等。相等则放弃保存。不相等则以链表的方式保存。如果链表的长度大于8,则改用红黑树结构。
特别注意:使用哈希表结构保存自定义对象时,要求要重写hashCode() 和 equals()方法。
2.LinkedHashSet:底层是哈希表+链表结构—> 可以保证元素的存取顺序
3.TreeSet:底层是红黑树结构。不能保存重复元素,可以对保存的元素进行排序或 自定义排序(传递一个比较器对象。)
数据结构
堆栈: 先进后出
队列: 先进先出
数组: 查询快,增删慢。
链表: 查询慢,曾删快。
红黑树: 查询特别快。可以对数据进行排序。
Collections: 是操作集合的工具类。
- public static boolean addAll(Collection c, T… elements):往集合中添加一些元素。
- public static void shuffle(List<?> list) 打乱顺序:打乱集合顺序。
- public static void sort(List list):将集合中元素按照默认规则排序。
- public static void sort( List list,Comparator<? super T> ):将集合中元素按照指定规则排序。
//注意:Collection 和 Collections 的区别
HashSet集合
集合之所以能够保证对象唯一,主要依赖于:hashCode()与equals()方法。
哈希值:
哈希值指的是对象通过调用Object类中的hashCode()方法,从而获取到的一个十进制的数值
Comparable接口
自定义类实现Comparable接口,使其具备比较大小的功能,并实现**compareTo()**方法
Comparator比较器
**public int compare(String o1, String o2)**比较其两个参数的顺序。
简述Comparable和Comparator两个接口的区别。
Comparable:自定义类如果需要排序,实现要实现此接口使其具备比较的功能,在书写比较方式的代码即可。
Comparator:强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort或 Arrays.sort),从而允许在排序顺序上实现精确控制。
TreeSet保存到这个集合中的数据,集合内部都会完成自动排序。
构造方法:
TreeSet() : 空参构造方法
TreeSet(Comparator comparator):接收比较器的构造方法,可以传递比较器,规定具体的比较方式。
Map集合
通过查看Map接口描述,看到Map有多个子类:
HashMap集合
LinkedHashMap集合。
Map接口中定义了很多方法,常用的如下:
public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。如果键值存在则覆盖。
public V remove(Object key): 把指定的键和对应的值在集合中删除,返回被删除元素的值。
public V get(Object key): 根据指定的键,在Map集合中获取对应的值。
Map接口的方法演示
public class MapDemo {
public static void main(String[] args) {
//创建 map对象
HashMap<String, String> map = new HashMap<String, String>();
//添加元素到集合
map.put("黄晓明", "杨颖");
map.put("文章", "马伊琍");
map.put("邓超", "孙俪");
System.out.println(map);
//String remove(String key)
System.out.println(map.remove("邓超"));
System.out.println(map);
// 想要查看 黄晓明的媳妇 是谁
System.out.println(map.get("黄晓明"));
System.out.println(map.get("邓超"));
}
}
Map集合遍历键找值方式
在Map集合体系中并没有给我们提供迭代遍历的方式,也就是说在Map集合中,我们无法使用Collection集合体系中的Iterator迭代器对Map集合进行遍历,在Map集合体系中给我们提供了下列方法:
public Set keySet(): 获取Map集合中所有的键,存储到Set集合中。
键找值方式:即通过元素中的键,获取键所对应的值
代码演示:
public class MapDemo01 {
public static void main(String[] args) {
//创建Map集合对象
HashMap<String, String> map = new HashMap<String,String>();
//添加元素到集合
map.put("胡歌", "霍建华");
map.put("郭德纲", "于谦");
map.put("薛之谦", "大张伟");
//获取所有的键 获取键集
Set<String> keys = map.keySet();
// 遍历键集 得到 每一个键
for (String key : keys) {
//key 就是键
//获取对应值
String value = map.get(key);
System.out.println(key+"的CP是:"+value);
}
}
}
Entry键值对对象
public Set<Map.Entry<K,V>> entrySet(): 获取集合中所有的键值对对象,保存到Set集合中。
Map中存放的是两种对象,一种称为key(键),一种称为value(值),它们在在Map中是一一对应关系,这一对对象又称做Map中的一个Entry(项)
对应键和对应值得方法:
**public K getKey():**获取Entry对象中的键。
**public V getValue():**获取Entry对象中的值。
在Map集合中也提供了获取所有Entry对象的方法:
public Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)。
LinkedHashMap
在HashMap下面有一个子类LinkedHashMap,它是链表和哈希表组合的一个数据存储结构。在保证key值对象唯一的前提下,还能保证元素的存取顺序。
public class LinkedHashMapDemo {
public static void main(String[] args) {
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
map.put("邓超", "孙俪");
map.put("李晨", "范冰冰");
map.put("刘德华", "朱丽倩");
Set<Entry<String, String>> entrySet = map.entrySet();
for (Entry<String, String> entry : entrySet) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
}
//注意:LinkedHashMap存取顺序是先存取,就在前面,后存取就在后面
JDK9 对集合添加的优化
Java 9,添加了几种集合工厂方法,更方便创建少量元素的集合、map实例。
新的List、Set、Map的静态工厂方法可以更方便地创建集合的不可变实例。
public class HelloJDK9 {
public static void main(String[] args) {
Set<String> str1 = Set.of("a","b","c");
//str1.add("c");这里编译的时候不会错,但是执行的时候会报错,因为是不可变的集合
System.out.println(str1);
Map<String,Integer> str2 = Map.of("a",1,"b",2);
System.out.println(str2);
List<String> str3 = List.of("a","b");
System.out.println(str3);
}
}
需要注意以下两点:
1:of()方法只是Map,List,Set这三个接口的静态方法,其父类接口和子类实现并没有这类方法,比如 HashSet,ArrayList等。
2:返回的集合是不可变的。