六. 集合框架
1. Collection接口
-
集合是java中提供的一种容器,可以用来存储多个数据
-
集合的体系结构
- 主要分为两大体系 : Collection和Map
- Collection表示一组对象
- Map表示一组映射关系或键值对
- Collection 根接口,子接口,List Set
- Collection 接口常用的方法
- 主要分为两大体系 : Collection和Map
方法 | 代码 |
---|---|
添加 | add |
是否包含 | contains |
删除 | remove |
集合中有几个元素 | size |
集合变成数组 | toArray |
清空集合 | clear |
判断是否为空 | isEmpty |
package com.demo;
import java.util.ArrayList;
import java.util.Collection;
public class Demo01 {
public static void main(String[] args) {
//创建一个Collection
Collection<String> collection = new ArrayList<>();
//添加
collection.add("zzz");
collection.add("aaa");
collection.add("bbb");
System.out.println(collection);
//集合是否包含
boolean flag = collection.contains("aaa");
System.out.println(flag);
//删除
boolean removeFlag = collection.remove("zzz");
System.out.println(removeFlag);
System.out.println(collection);
//集合中有几个元素
int size = collection.size();
System.out.println(size);
//集合变成数组
Object[] objects = collection.toArray();
for (int i = 0; i < objects.length; i++) {
System.out.println(objects[i]);
}
//清空集合 clear
collection.clear();
System.out.println(collection);
//判断是否为空
System.out.println(collection.isEmpty());
}
}
2. Iterator迭代器
- 遍历获取集合中的所有元素
- 不是所有的集合都能使用Iterator迭代器,使用前提,集合需要是Iterator接口的子接口或者是实现类,Map是不可以使用Iterator迭代器
- 注意:不要在使用Iterator迭代器进行迭代时,调用Collection中的remove方法
package com.demo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
//Iterator迭代器
public class Demo02 {
public static void main(String[] args) {
Collection<String> collection = new ArrayList<>();
collection.add("小明");
collection.add("小红");
collection.add("小黑");
collection.add("小白");
//迭代器
//1.创建迭代器对象
Iterator<String> iterator = collection.iterator();
//2.判断下一个位置是否有元素
while (iterator.hasNext()){
//3.指向下一个元素,获取出来
String value = iterator.next();
System.out.println(value);
}
}
}
3. 增强for循环
迭代器代码的一个简化版,底层是迭代器
for(元素的数据类型 变量名:要遍历的集合或数组){操作代码}
//增强for
for (String value:collection){
System.out.println(value);
}
4. List接口
-
List接口
- List接口是Collection接口的子接口
- List集合中存储的数据是有序的,List集合可以有重复元素
- List接口有很多实现类,底层结构有数组和链表
-
List集合中常用的操作方法
package com.kgc.Demo01; import java.util.ArrayList; import java.util.List; public class Demo01 { public static void main(String[] args) { List<User> listUser = new ArrayList<>(); User u1 = new User("Lucy",1); User u2 = new User("Lily",2); listUser.add(u1); listUser.add(u2); //遍历集合 for (User user:listUser){ System.out.println(user.getName()); } System.out.println("-------"); //创建List集合 List<String> list = new ArrayList<>(); list.add("王语嫣"); list.add("aaa"); //普通for循环遍历 for (int i = 0; i < list.size(); i++) { String s = list.get(i); System.out.println(s); } System.out.println("-------"); //删除方法 remove list.remove(1); for (int i = 0; i < list.size(); i++) { String s = list.get(i); System.out.println(s); } System.out.println("-------"); list.remove("王语嫣"); for (int i = 0; i < list.size(); i++) { String s = list.get(i); System.out.println(s); } } }
-
List接口有很多实现类,常用ArrayList , linkList , vector
- ArrayList
- 数据存储的结构是数组结构,元素增删慢,查找块
- 创建的List有三部分:Object数组,size大小,modCount版本
- 创建List集合后,Object数组初始化大小是0,添加数据大小加1
package com.kgc.Demo01; import java.util.ArrayList; import java.util.List; public class Demo02 { public static void main(String[] args) { List<String> list = new ArrayList<>(); //添加10个数据 for (int i = 1; i <=10; i++) { list.add("大数据"+i); } list.add("linux"); System.out.println(list); } }
- vector
- 创建对象时,有四步
- object数组,elemenrCount元素数量,默认0,modCount版本
- 创建对象时,有四步
package com.kgc.Demo01; import java.util.ArrayList; import java.util.List; import java.util.Vector; public class Demo03 { public static void main(String[] args) { List<String> list = new Vector<>(); //添加10条数据 for (int i = 1; i <=10; i++) { list.add("java"+i); } list.add("mysql"); System.out.println(list); } }
- LinkedList
- 数组存储的结构是链表(双向)
- 创建时包含四部分,size元素的数量,first,last,modCount
- 添加元素时,第一次添加元素的时候,作为首节点和尾结点
- 再次添加时,在首节点下一个添加一个节点,可以指向上一个节点
- 数组存储的结构是链表(双向)
package com.kgc.Demo01; import java.util.LinkedList; import java.util.List; public class Demo04 { public static void main(String[] args) { List<String> list = new LinkedList<>(); //添加3个 list.add("java"); list.add("linxu"); list.add("mysql"); System.out.println(list); } }
- ArrayList
5. ArrayList和Vector的区别
这两个类都实现了 List 接口(List 接口继承了 Collection 接口), 他们都是有序集合
-
线程安全:
Vector 使用了 Synchronized 来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。
vector的add方法 -
性能:
ArrayList 在性能方面要优于 Vector。
因为ArrayList没有使用synchronized加锁, 不加锁, 所以处理速度会快一些 -
扩容:
ArrayList 和 Vector 都会根据实际的需要动态的调整容量, 只不过在 Vector 扩容每次会增加 1 倍, 而ArrayList 只会增加 50%。vector扩容:如果不是指定的话,会扩大一倍
ArrayList扩容:增加1/2的容量
-
同步
Vector类的所有方法都是同步的
可以由两个线程安全地访问一个Vector对象,但是一个线程访问Vector的话代码要在同步操作上耗费大量的时间。
Arraylist不是同步的,所以在不需要保证线程安全时时建议使用Arraylist
6. ArrayList和Vector,LinkedList的区别
-
ArrayList:
ArrayList 是动态数组,动态的意思是可以随时增加数组长度,众所周知,普通数组的长度是定死的,想要增加长度,就必须重新定义一个固定长度的数组,然后在把元素加进去,但是ArrayList可以随意增加或删除元素,这就让我们在操作的时候变得更灵活,动态数组每个元素都有一个下标,也就是标识这个元素的位置,通过这个下标,计算机就可以知道这个元素存放在内存的哪个位置,所以ArrayList 想要遍历查找某个元素的时候很快就能找到!而且,ArrayList也是线程不安全的
-
LinkedList:
LinkedList的底层就是用双向链表实现的,因为链表本身是无序的,所以LinkedList 插入或者删除都很快,但是要查找或者遍历的时候就会很慢,因为双向链表每次查找某个元素的时候都会在内部遍历一遍,直到找到那个指定下标的元素为止,另外,LinkedList 的内存占用要比ArrayList大,因为LinkedList除了存储数据之外,还存储了2个指针,一个指向前一个元素,一个指向后一个元素。
-
Vector:
总体来说,Vector除了是线程安全的之外,Vector 和 ArrayList 的底层存储结构基本相似,但又不完全相同。
-
ArrayList和LinkedList区别:
-
相同点:
LinkedeList和ArrayList都实现了List接口。
ArrayList和LinkedList是两个集合类,用于存储一系列的对象引用(references)。 -
不同点:
ArrayList底层的实现数组,而LinkedList是双向链表。
ArrayList进行随机访问所消耗的时间是固定的,因此随机访问时效率比较高。
LinkedList是不支持快速的随机访问的,但是在插入删除时效率比较高。
-
-
ArrayList和Vector区别:
-
相同点:
ArrayList和Vector都是用数组实现的。
默认初始化大小都是10 -
不同点
Vector多线程是安全的,而ArrayList不是。Vector类中的方法很多有synchronized进行修饰,这样就导致了Vector在效率上无法与ArrayList相比;
两个都是采用的线性连续空间存储元素,但是当空间不足的时候,两个类的增加方式是不同的。(ArrayList每次存储时会检查空间大小,不够时会扩充为原来的1.5倍,Vector会扩充为原来空间的2倍)
Vector可以设置增长因子,而ArrayList不可以。
ArrayList有三个构造方法,Vector有四个构造方法。
-
-
ArrayList,Vector, LinkedList 的存储性能和特性:
ArrayList 和 Vector 都是使用数组方式存储数据,此数组元素数大于实际存储的数 据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组 元素移动等内存操作,所以索引数据快而插入数据慢,Vector 由于使用了 synchronized 方法(线程安全)
通常性能上较 ArrayList 差,而 LinkedList 使用双向链表实现存储,按序号索引数 据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插 入速度较快
ArrayList 在查找时速度快,LinkedList 在插入与删除时更具优势
-
总结:
ArrayList, Vector 底层是由数组实现,LinkedList 底层是由双线链表实现,从底层的实现可以得出它们的性能问题
ArrayList, Vector 插入速度相对较慢,查询速度相对较快,而LinkedList 插入速度较快,而查询速度较慢
再者由于 Vevtor 使用了线程安全锁,所以ArrayList 的运行效率高于 Vector
7. Set接口
-
Set接口是Collection子接口
-
Set接口不能重复,是无序的
-
Set的遍历可以使用迭代器和增强for,实现类有 HashSet , TreeSet , LinkedHashSet
- HashSet
package com.kgc.Demo02; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class Demo01 { public static void main(String[] args) { Set<String> set = new HashSet<>(); //添加数据 set.add("abc"); set.add("www"); set.add("efg"); //增强for循环遍历 for (String value:set){ System.out.println(value); } System.out.println("---------"); //Iterator迭代器遍历 //创建对象 Iterator<String> iterator = set.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } }
-
TreeSet
-
LinkedHashSet
8. Map接口
-
一一对应的,这个叫映射
-
java中提供了专门的集合类用来存放这种关系对象,即java.util.Map<K,V> 键值对存储方式
-
Map中的集合不能包含重复的键,值可以重复,每个键只能对应一个值
-
常用的方法
1 方法 添加方式 put(key , value) 根据key获取对应value的值 get(Object key) 移除 remove(Object key) 返回map命令所有的key Set< k > keySet() 返回所有的value Collection< v > value 清空 clear() package com.kgc.Demo02; import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; public class Demo02 { public static void main(String[] args) { //创建一个map对象 Map<String,String> map = new HashMap<>(); //添加 map.put("101","Lucy"); map.put("102","Lily"); map.put("103","Lilei"); System.out.println(map); //根据key的值获取value String s = map.get("103"); System.out.println(s); //移除 String remove = map.remove("102"); System.out.println(remove); System.out.println(map); //获取所有的value Collection<String> values = map.values(); System.out.println(values); //获取所有的key Set<String> strings = map.keySet(); System.out.println(strings); //清空 map.clear(); System.out.println(map); } }
-
Map集合遍历
- 第一种 获取map里的所有key,根据key获取value
package com.kgc.Demo02; import java.util.HashMap; import java.util.Map; import java.util.Set; public class Demo03 { public static void main(String[] args) { Map<String,String> map = new HashMap<>(); map.put("101","Lucy"); map.put("102","Lily"); map.put("103","Lilei"); //1. 获取所有的key Set<String> keys = map.keySet(); //2. 遍历Set类型的keys for (String key:keys){ String value = map.get(key); System.out.println(key+" : "+value); //System.out.println(map.get(key));
- 第二种 直接获取map里的key:value关系,获取key和value
//第二种遍历 Set<Map.Entry<String, String>> entries = map.entrySet(); for (Map.Entry<String, String> entry:entries){ String key = entry.getKey(); String value = entry.getValue(); System.out.println(key+" : "+value); //System.out.println(entry); } } }
package com.kgc.Demo02; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; /* 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 Demo04 { public static void main(String[] args) { Map<String,String> map = new HashMap<>(); map.put("1","张三"); map.put("2","李四"); Set<Map.Entry<String, String>> entries = map.entrySet(); Iterator<Map.Entry<String, String>> it = entries.iterator(); while(it.hasNext()){ Map.Entry<String, String> entry = it.next(); System.out.println(entry.getKey()+" : "+entry.getValue()); } System.out.println("----------"); for (Map.Entry<String, String> entry1:entries){ System.out.println(entry1.getKey()+" : "+entry1.getValue()); } } }
//练习 /* 计算一个字符串,每个字符出现的次数 如 abcabcaabbccd a:4 b:4 c:4 d:1 */ package com.kgc.Demo02; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Scanner; /* 计算一个字符串,每个字符出现的次数 如 abcabcaabbccd a:4 b:4 c:4 d:1 */ public class Demo05 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("请输入一个字符串:"); String str = sc.next(); Map<Character,Integer> map = new HashMap<>(); //System.out.println(str.toCharArray()); for(char c:str.toCharArray()){ //1. 判断字符是否在map集合中key里有没有 if(map.containsKey(c)){ //1. 如果在: 次数+1 map.put(c,map.get(c)+1); }else{ //2. 如果不在: put("a",1) map.put(c,1); } } //System.out.println(map); for (Character key:map.keySet()){ System.out.println(key+"="+map.get(key)); } } }
-
Collections
package com.kgc.Demo02; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Demo06 { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("小米"); list.add("苹果"); list.add("华为"); list.add("OPPO"); list.add("vivo"); for (String s:list){ System.out.println(s); } System.out.println("----------"); //collections里sort排序 Collections.sort(list); for (String s:list){ System.out.println(s); } //查询集合中元素的最大值 System.out.println("最大值:"+Collections.max(list)); System.out.println("最小值:"+Collections.min(list)); System.out.println("----------"); //查询集合中指定的元素,查询下标 System.out.println(Collections.binarySearch(list,"OPPO")); System.out.println("----------"); //反转倒叙输出 Collections.reverse(list); for (String s:list){ System.out.println(s); } System.out.println("----------"); //往集合中添加元素 Collections.addAll(list,"111","222","333","444","555"); for (String s:list){ System.out.println(s); } System.out.println("----------"); } }