看图可知,主要分为两类:Collection 和 Map,Collection
主要用于存储一组对象,Map
用于存储键-值对。
对这二者再细分
Collection接口:
Map接口
一、Collection 接口的接口 对象的集合(单列集合)
二、Map 接口 键值对的集合 (双列集合)
//因为Collection是接口,不能实例化,所以我们用他的一个实现类ArrayList来演示
List list = new ArrayList<>();
list.add("mk");
list.add(true);
list.add(12.3);
也可以存储指定类型的数据
List list = new ArrayList<>();
list.add("mk");
int size(); |
获取集合大小 |
boolean isEmpty(); |
判断是否为空 |
boolean contains(Object var1); |
判断是否包含 |
Object[] toArray(); |
将集合转换为数组 |
boolean add(E var1); |
添加元素 |
boolean addAll(Collection var1); |
添加一个集合的全部元素 |
boolean remove(Object var1); |
删除集合中某个元素 |
boolean remove(int index); |
删除集合中指定下标的元素 |
boolean removeAll(Collection var1); |
删除一个集合的全部元素 |
void clear(); |
清空集合 |
boolean containsAll(Collection var1); |
判断是否包含另一个集合的元素 |
boolean equals(Object var1); |
判断是否相同 |
default Spliterator spliterator(); |
得到该集合的分离器 |
default Stream stream(); |
转换为Stream流 |
default Stream parallelStream(); |
转换为Stream并行流 |
测试
public class Test {
public static void main(String[] args) {
//定义一个集合并向上转型
Collection obj = new ArrayList<>();
//1.int size(); 获取集合大小
int size = obj.size();
//2.boolean isEmpty(); 判断是否为空
boolean empty = obj.isEmpty();
//3.boolean contains(Object var1); 判断是否包含
boolean contains = obj.contains(null);
//4.Object[] toArray(); 将集合转换为数组
Object[] objects = obj.toArray();
//5.boolean add(E var1); 向集合增加元素
boolean result = obj.add("Hello World");
//6.boolean remove(Object var1); 向集合移除元素
boolean remove = obj.remove(null);
//7.boolean containsAll(Collection> var1); 判断是否包含另一个集合的元素
boolean containsResult = obj.containsAll(new ArrayList<>());
//8.boolean addAll(Collection extends E> var1); 添加一个集合的全部元素
boolean addAllResult = obj.addAll(new ArrayList<>());
//9.boolean removeAll(Collection> var1); 删除一个集合的全部元素
boolean removeAllResult = obj.removeAll(new ArrayList<>());
//10.void clear(); 清空集合
obj.clear();
//11.boolean equals(Object var1); 判断是否相同
boolean equalsResult = obj.equals(null);
//12.default Spliterator spliterator(); 得到该集合的分离器
Spliterator spliterator = obj.spliterator();
//13.default Stream stream(); 转换为Stream流
Stream stream = obj.stream();
//14.default Stream parallelStream(); 转换为Stream并行流
Stream stringStream = obj.parallelStream();
}
}
两种遍历方法:
//1. 先得到collection对应的迭代器
Iterator iterator = collection.iterator();
//2. 开始遍历
//判断是否还有下一个元素
while (iterator.hasNext()) {
//返回下一个元素
Object next = iterator.next();
System.out.println(next);
}
//重置iterator
iterator = collection.iterator();
作用
相当于一个指针,用于遍历一个集合
1.为什么需要迭代器?
在实际应用中经常需要将容器遍历判断满足业务需求。
2.如何实现迭代?
Iterator类中有 hasNext()和next() 两个方法,因为遍历过程首先得判断是否为空,不为空才能继续遍历。
Iterator类具有remove()方法,因为Collection类中的removeIf()方法是jdk1.8后才有的,所以需要满足能有通过逻辑删除的需求。
3.如果希望再次使用一个迭代器,需要重置
因为使用完一次迭代器之后,指针会指向最后一个元素,我们想再次使用,就得将其重置,否则会报错
4.生成代码的快捷键
itit
示例
public class Test {
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add(new Book("三国演义","罗贯中",10.1));
collection.add(new Book("小李飞刀","古龙",5.1));
collection.add(new Book("海贼王","尾田",34.6));
//1. 先得到collection对应的迭代器
Iterator iterator = collection.iterator();
//2. 开始遍历
//判断是否还有下一个元素
while (iterator.hasNext()) {
//返回下一个元素
Object next = iterator.next();
System.out.println(next);
}
//重置iterator
iterator = collection.iterator();
}
}
class Book {
String name;
String author;
double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
for (Object object : collection) {
System.out.println(object);
}
增强for循环,就是foreach循环,可以代替iterator迭代器
特点:增强for就是简化版的iterator,本质一样,它的底层也是 Iterator。数组和集合都能用。
快捷键:
collection.for
示例
public class Test {
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add(new Book("三国演义","罗贯中",10.1));
collection.add(new Book("小李飞刀","古龙",5.1));
collection.add(new Book("海贼王","尾田",34.6));
for (Object object : collection) {
System.out.println(object);
}
}
}
class Book {
String name;
String author;
double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
Collection接口的方法,List接口和Set接口都有,但是List接口和Set接口他们自己的方法,对方是没有的。
特点
也就是可以 用 list.get(3) 来拿到第4个元素
除去Collection接口的方法,List接口还有自己独特的方法
因为List接口是有序的,所以它可以用很多带有索引的方法
package edu.tjdz.javaSE.collection;
import java.util.*;
/*
测试List接口中的常用方法
1、List集合存储元素特点:有序可重复
有序:List集合中元素由下标。
从0开始,以1递增。
可重复:存储一个1,还可以在存储一个1.
2、List即是Collection接口中的子接口,那么肯定List接口有自己“特色”的方法:
以下只列出List特有的常用的方法
void add(int index, E element) 在列表的指定位置添加元素(第一个参数是下标)
Object get(int index) 根据下标获取元素(元素的下标,从0开始,以1递增)
int indexOf(Object o) //获取指定对象第一次出现的索引
int lastIndexOf(Object o) //获取指定对象最后一次出现的索引
Object remove(int index) //删除指定下标位置的元素
Object set(int index, Object element) //修改指定位置元素(元素下标,修改的值)
*/
public class CollectionTest07 {
public static void main(String[] args) {
//创建List集合
//List myList = new LinkedList();
//List myList = new Vector();
List myList = new ArrayList();
//添加元素
myList.add("A"); //默认都是向集合尾部添加元素
myList.add("B");
myList.add("C");
myList.add("D");
myList.add("A");
//在列表的指定位置添加元素(第一个参数是下标)
//这个方法使用不多,因为对于ArrayList集合来说,效率较低(因为ArrayLIst底层是数组,添加的时候会涉及到元素位移的问题)
myList.add(1,"KING");
//迭代
Iterator it = myList.iterator();
while(it.hasNext()){
Object elt = it.next();
System.out.println(elt);
}
System.out.println("------------------------------");
//根据下标
Object firstobj = myList.get(0);
System.out.println(firstobj); //A
//因为有下标,所以List集合有自己特殊的遍历方式
//根据下标遍历【List集合特有的方式,Set没有。】
for(int i=0;i
List可以用collection接口的两种方法:Iterator迭代器、foreach循环
还能有一种自己独特的方法,因为List接口是有序的,所以可以用索引的方式来遍历
//遍历集合
for(int i=0;i
底层 |
查询 |
增删 |
线程安全 |
效率 |
扩容倍数 |
|
ArrayList |
数组 |
快 |
慢 |
不安全 |
高 |
如果有参构造,默认大小:参数,满后按照1.5倍扩容 如果无参构造,默认大小:0,第一次容量扩大到10,从第二次开始1.5倍扩容 |
Vector |
数组 |
快 |
慢 |
安全 |
低 |
如果有参构造,默认大小:参数,满后每次扩大两倍 如果无参构造,默认大小:10,满后就按照2倍扩容 |
LinkedList |
链表 |
慢 |
快 |
不安全 |
高 |
链表,不用扩容 |
扩容机制
2和3 分别就是下图中的两个
注意:代码中的右移就是÷2的意思
(1)Vector可以实现可增长的对象数组。与数组一样,可以使用整数索引进行访问的组件。不过,Vector的大小是可以增加或者减小的,以便适应创建Vector后进行添加或者删除操作。
(2)同时Vector是线程安全的!底层使用的是synchronized进行加锁。
扩容机制
如果有参构造,默认大小:参数,满后每次扩大两倍
如果无参构造,默认大小:10,满后就按照2倍扩容
底层机制
特点
除去Collection接口的方法,Set接口也有自己独特的方法
也就是Collection接口的两种遍历方法:Iterator迭代器、foreach循环
因为Set是无序的,所以不能使用索引的方式来遍历
public class SetTest {
public static void main(String[] args) {
Set set = new HashSet();
// Hashset不能添加相同的元素/数据?
set.add("lucy");//ok
set.add( "lucy");//no
set.add(new Dog("tom" ));//OK
set.add(new Dog( "tom"));//0k
//再加深一下。非常经典的面试题。
set.add(new String("hsp"));//ok
set.add(new String("hsp"));//no
System.out.println( "set=" + set);
}
}
class Dog{
String name;
Dog(String name){
this.name = name;
}
}
输出
set=[hsp, 集合.Dog@4554617c, 集合.Dog@1b6d3586, lucy]
lucy那里,因为地址一样,都是常量池中的,所以是重复元素,所以第二个不能加入。
Dog那里,因为两个dog 都是新的对象,地址不一样,所以不算重复的元素,所以可以加入。
那第三对 是为什么?
Java中哈希集(HashSet)概念,实现以及操作_java hashset_Sueko的博客-CSDN博客
特点
注意:这里讲的是JDK8的Map接口特点
添加、删除、修改操作:
Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
void putAll(Map m):将m中的所有key-value对存放到当前map中
Object remove(Object key):移除指定key的key-value对,并返回value
void clear():清空当前map中的所有数据
元素查询的操作:
Object get(Object key):获取指定key对应的value
boolean containsKey(Object key):是否包含指定的key
boolean containsValue(Object value):是否包含指定的value
int size():返回map中key-value对的个数
boolean isEmpty():判断当前map是否为空
boolean equals(Object obj):判断当前map和参数对象obj是否相等
元视图操作的方法:
Set keySet():返回所有key构成的Set集合
Collection values():返回所有value构成的Collection集合
Set entrySet():返回所有key-value对构成的Set集合
Map 接口 键值对的集合 (双列集合)
Map接口的常用实现类:HashMap(子类LinkedHashMap)、TreeMap和Hashtable(子类Properties).
先用map.KeySet()方法拿到所有的key,将这些key存到一个Set集合中,再遍历这些key,用map.get(key)方法拿到value
可以用Set集合遍历的foreach循环遍历key,也可以用Set集合的迭代器key
注意:不推荐这种方法,因为只能获取key,要想获取对应的value,需要重复计算,效率低
public static void main(String[] args) {
Map map = new HashMap();
map.put("张三","李四");
map.put("路飞","女帝");
map.put("鸣人","雏田");
map.put("佐助","小樱");
map.put("邓超","孙俪");
System.out.println("第一种:用for循环--------------");
for(Object key : map.keySet()){
System.out.println(key + "-" + map.get(key));
}
System.out.println("第二种:用迭代器--------------");
Iterator iterator = map.keySet().iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
System.out.println(key + "-" + map.get(key));
}
}
用map.values() 方法拿到所有的value,存到一个collection中,在用collection接口的两种遍历方法去遍历
注意:这种方法只能取出value,不能取出key,不推荐
public static void main(String[] args) {
Map map = new HashMap();
map.put("张三","李四");
map.put("路飞","女帝");
map.put("鸣人","雏田");
map.put("佐助","小樱");
map.put("邓超","孙俪");
Collection values = map.values();
System.out.println("第一种:用for循环--------------");
for(Object value : values){
System.out.println(value);
}
System.out.println("第二种:用迭代器--------------");
Iterator iterator = values.iterator();
while (iterator.hasNext()) {
Object value = iterator.next();
System.out.println(value);
}
}
首先通过map.entrySet()方法,可以获取到一个Set集合,这个集合中的每一个元素就是Map中的一个键值对。然后通过循环遍历这个Set集合,可以依次取出每对的键和值。该方法使用了foreach循环,代码简洁明了,且能获取Map的键和值,是最常见且多数情况最可取的遍历方式。
注意:推荐使用这种方式,效率高
public static void main(String[] args) {
Map map = new HashMap();
map.put("张三","李四");
map.put("路飞","女帝");
map.put("鸣人","雏田");
map.put("佐助","小樱");
map.put("邓超","孙俪");
Set entrySet = map.entrySet();
System.out.println("第一种:用for循环--------------");
for(Object entry : entrySet){
//将entry 转换成 Map.Entry
Map.Entry m =(Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}
System.out.println("第二种:用迭代器--------------");
Iterator iterator = entrySet.iterator();
while (iterator.hasNext()) {
Object entry = iterator.next();
//将entry 转换成 Map.Entry
Map.Entry m =(Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}
}