一、集合
集合类定义于java.util包中。
集合类存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用。
可以简单理解为,集合就是为了存储数据而定义的一个容器,只能存储引用类型的数据,其实存储的是对象的引用。
二、常用集合继承、实现关系图
三、Collection接口
Collection是集合的顶层接口(JDK1.5开始,Iterable<E>接口才是顶层接口,实现这个接口允许对象成为 "foreach" 语句的目标)。
由于所有集合接口都继承了Collection接口,所以Collection接口定义了集合的共性,但它又是接口,不能被实例化,所以想要使用它其中的方法,只能创建实现类对象。下面使用其实现类ArrayList来学习其中的一些方法。
例:
//void clear() 方法
@Test
public void test1(){
Collection<String> coll = new ArrayList<String>();
coll.add("abc"); //添加元素方法
coll.add("cde");
System.out.println(coll);
coll.clear(); //清除集合中所有元素
System.out.println(coll);
}
//boolean contains(Object o) 方法
@Test
public void test2(){
Collection<String> coll = new ArrayList<String>();
coll.add("abc");
coll.add("cde");
boolean b = coll.contains("abc"); //判断对象是否存在于集合中
System.out.println(b);
}
//int size() 方法
@Test
public void test3(){
Collection<String> coll = new ArrayList<String>();
coll.add("abc");
coll.add("cde");
int i = coll.size(); //返回元素个数
System.out.println(i);
}
// Object[] toArray() 方法
@Test
public void test4(){
Collection<String> coll = new ArrayList<String>();
coll.add("abc");
coll.add("cde");
Object[] array = coll.toArray(); //把集合中的元素转成一个数组
for (Object object : array) {
System.out.println(object);
}
}
//boolean remove(Object o) 方法
@Test
public void test5(){
Collection<String> coll = new ArrayList<String>();
coll.add("abc");
coll.add("cde");
boolean b = coll.remove("abc"); //移除集合中的指定的元素,如果存在返回true
System.out.println(b);
}
//迭代器 Iterator<E>接口 集合通用的迭代方式
//boolean hasNext() //判断集合中是否还有可以被取出的元素,有返回true
//E next() //取出集合中的下一个元素
@Test
public void test6(){
Collection<String> coll = new ArrayList<String>();
coll.add("abc");
coll.add("cde");
Iterator<String> iterator = coll.iterator();
while(iterator.hasNext()){
String next = iterator.next();
System.err.println(next);
}
}
//增强for循环 遍历集合 、数组
//弊端:没有索引,不能操作容器里面的元素
@Test
public void test7(){
Collection<String> coll = new ArrayList<String>();
coll.add("abc");
coll.add("cde");
for (String string : coll) {
System.out.println(string.length()); //遍历的时候可以调用对象的方法
}
}
四、List接口
List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。
List 接口存储一组不唯一,有序(插入顺序)的对象。
以下继续使用其实现类ArrayList来学习其中的一些方法。
例:
// void add(int index, E element) 根据索引插入元素
@Test
public void test1(){
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("abc");
list.add("abc");
list.add("abc");
System.out.println(list);
list.add(1, "cde"); //根据索引插入元素,索引上原有的数据往后顺延
System.out.println(list);
}
// E get(int index) 返回集合中指定位置的元素
@Test
public void test2(){
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("abc");
list.add("abc");
list.add("abc");
String a = list.get(2); //根据索引取元素
System.out.println(a);
}
// E remove(int index) 移除指定位置上的元素,返回移除的元素
@Test
public void test3(){
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("cde");
list.add("fff");
list.add("ggg");
String remove = list.remove(1); //移除指定位置的元素 返回移除的元素
System.out.println(remove);
System.out.println(list);
}
// E set(int index, E element) 修改指定位置的元素 返回修改之前的元素
@Test
public void test4(){
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("cde");
list.add("fff");
list.add("ggg");
String set = list.set(1, "123"); //修改指定位置的元素 返回修改之前的元素
System.out.println(set);
System.out.println(list);
}
//迭代器的并发修改异常
@Test
public void test5(){
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("cde");
list.add("fff");
list.add("ggg");
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String string = iterator.next();
if(string.equals("fff")){
list.add("ccc"); //如果取出来的元素等于fff 就添加一个ccc 这样会出现并发修改异常
}
System.out.println(list);
}
}
ArrayList实现类自身的特点:
其底层是长度可变数组的实现。
通过其构造方法可以指定数组的初始大小,默认为10.
查询元素效率高,增删元素效率低。
LinkedList实现类自身的特点:
其底层是基于链表的数据结构实现。
增删元素效率高,查询效率低。
除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。
例:
//LinkedList的特性
//void addFirst(E e) 在列表的开头添加元素
//void addLast(E e) 在列表的结尾添加元素
// E getFirst() 获取链表的第一个元素
// E getLast() 获取链表的第一个元素
// E removeFirst 移除并返回此列表的第一个元素
// E removeLast 移除并返回此列表的最后一个元素
@Test
public void test6(){
LinkedList<String> list = new LinkedList<>();
list.add("abc");
list.addFirst("ced"); //在列表的开头添加元素
list.addLast("ccc"); //在列表的结尾添加元素
System.out.println(list);
if(list.isEmpty()){ //如果链表为空 则不能取元素
String first = list.getFirst(); //获取链表的第一个元素
String last = list.getLast(); //获取链表的第一个元素
System.out.println(first);
System.out.println(last);
}
}
五、set接口
Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素,无索引。
Set 接口存储一组唯一,无序的对象,最多包含一个 null 元素。
使用其实现类HashSet来学习其中的方法。
例:
//set是存取无序的集合
@Test
public void test1(){
Set<String> set = new HashSet<>();
set.add("aaa");
set.add("bbb");
set.add("ccc");
set.add("ddd");
set.add("ddd"); //不允许存储重复 自动忽略重复的元素(根据哈希值来判断是否重复 ,相等则表示重复)
for (String string : set) { //取出元素的顺序与存的顺序不一致
System.out.println(string);
}
}
HashSet自身的特性:
底层是基于哈希表的数据结构实现。
此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
LinkedHashSet自身的特点:
底层是基于链表和哈希表的数据结构实现。
此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。插入顺序不受在 set 中重新插入的元素的影响。
例:
//LinkedHashSet有自身的特性,具有顺序,存、取的顺序一致
@Test
public void test2(){
LinkedHashSet<Integer> link = new LinkedHashSet<>();
link.add(1);
link.add(2);
link.add(3);
for (Integer integer : link) {
System.out.println(integer);
}
}
六、双列集合-Map<K,V>
Map集合,以键值对(key-value)的方式来存储数据。
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
使用其实现类HashMap来学习其中的方法。
例:
// V put(K key, V value) 方法 添加键值对,返回值一般情况下为null,存储重复键时,返回覆盖之前的值
@Test
public void test1(){
Map<String,String> map = new HashMap<>();
map.put("username", "笑笑");
map.put("username", "哈哈"); //键唯一,相同键会覆盖
map.put("username1", "笑笑");
String value = map.put("username", "笑笑"); //返回值一般情况下为null,存储重复键时,返回覆盖之前的值
System.out.println(value);
System.out.println(map);
}
// V get(Object key) 方法 通过键对象 获取值对象
@Test
public void test2(){
Map<String,String> map = new HashMap<>();
map.put("username", "笑笑");
String string = map.get("username"); // 通过键对象 获取值对象 如果没有这个键,返回null
System.out.println(string);
}
// V remove(Object key) 方法 移除集合中的键值对,返回移除之前的值
@Test
public void test3(){
Map<String,String> map = new HashMap<>();
map.put("username", "笑笑");
String remove = map.remove("username"); //移除集合中的键值对,返回移除之前的值 如果没有 返回null
System.out.println(remove);
}
//Map集合的遍历 Set<K> keySet() 把所有的Key放到了一个Set集合中 (键获取值的方式)
@Test
public void test4(){
Map<String,String> map = new HashMap<>();
map.put("username", "笑笑");
map.put("username1", "哈哈");
map.put("username3", "嘻嘻");
Set<String> set = map.keySet(); //调用keySet()方法 把键存储到Set集合中(是HashMap中的一个内部类实现的)
for (String key : set) { //遍历set集合,获取所有的key
String value = map.get(key); //调用map的get方法获得key对应的值
System.out.println(value);
}
}
// Set<Map.Entry<K,V>> entrySet() 通过键值对的映射关系来遍历
@Test
public void test5(){
Map<String,String> map = new HashMap<>();
map.put("username", "笑笑");
map.put("username1", "哈哈");
map.put("username3", "嘻嘻");
Set<Map.Entry<String,String>> set = map.entrySet(); //将映射关系对象存储到se集合
for (Map.Entry<String, String> entry : set) { //遍历set集合
//System.out.println(entry); //获得键值对 对像entry
/*String key = entry.getKey(); //通过getKet获得键
System.out.println(key);*/
String value = entry.getValue(); //通过getValue获得值
System.out.println(value);
}
}
HashMap自身的特点:
基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键,此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
LinkedHashMap自身的特点:
存取元素的顺序相同。
例:
//LinkedHashMap,继承自HashMap,保证了迭代的顺序
@Test
public void test7(){
LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put("a", "笑笑");
map.put("b", "笑笑1");
map.put("c", "笑笑2");
System.out.println(map);
}