java.util
List
Collection下有两个数据结构,一个是ArrayList,一个是LinkedList。
其中ArrayList的底层是Object[]数组,优势在于可以随机访问get。
而LinkedList的底层是链表,访问某个元素的效率比ArrayList低,因为需要移动指针,但优势在于需要大量增删改的时候速度很快。
在选择上,如果要进行大量的增删操作,建议LinkedList。如果要进行大量的改查操作,建议ArrayList。
LinekedList
常用方法:
add()添加元素到链表尾部
addFirst()添加元素到链表头部
addLast()添加元素到链表尾部
get(int index) 获取第index个元素
remove(int index)删除第index个元素
size()返回链表的长度
clear()清空链表
ArrayList
==优点:==访问单个元素特别快,因此多用于改查操作。
==缺点:==比如删除,插入这种动作需要大部分元素移动,不适用于大数据量的操作。
构造方法
//不推荐 ArrayList<Integer> n = new ArrayList<>(); //推荐用接口代替具体实现类 List<Integer> list0 = new ArrayList<>();
add() 添加元素
set(int index,E e) 把第index个元素修改为e
get(int index)获取第index个元素
size() 方法
addAll(Collection<> c) 将另一个Collection集合的元素全部添加进来
indexOf(Object o) 返回元素 o 的下标
实例
List<Integer> list0 = new ArrayList<>(); List<Integer> list1 = new ArrayList<>(); list1.add(2); list1.add(3); list0.add(1); list0.add(0,2);//被插入的位置及后面所有元素都向后移动一个单位 System.out.println("list0的大小是"+ list0.size()+" list0的内容为:"+ list0.toString()); System.out.println("list1的大小是"+ list0.size()+" list1的内容为:"+ list0.toString()); System.out.println("修改list0的第一个位置为 0 "); list0.set(0,0); System.out.println(list0.toString()); System.out.println("把list1中所有元素移动到list0中,效果为:"); list0.addAll(list1); System.out.println(list0.toString());
运行结果:
遍历方式
遍历和遍历数组一致,无非数组长度的表示不同
toString() 已经写好直接用
System.out.println(list0.toString());
for循环
for(int i=0;i<list0.size();i++){ System.out.print(list0.get(i)+" "); }
加强for循环
注意:加强for循环的数据类型应该为包装类
for(Integer element:list0){ System.out.print(num); }
迭代器
ArrayList<Integer> link = ArrayList<>(); Iterator<Integer> iterator = link.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); }
运行结果:
Set
Set集合也可以当作数组来用,不过Set集合中不允许存储重复的元素,因此经常使用Set集合去重。
HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。底层数据结构是哈希表;
TreeSet底层是红黑树,TreeSet可以确保集合元素处于排序状态。
需要注意的是:
HashSet并不具备自动排序的功能,但是有些时候放进HashSet中的元素也会有顺序,然而这只是一种巧合,如果放进去的元素很多,HashSet并不能保证其顺序。
TreeSet具备自动排序的功能,将Integer或者Double放进TreeSet会自动帮我们排序,但是如果我们想将对象放进TreeSet,必须要让对象的类继承Comparable接口,并重写compareTo方法,使其具备比较大小的能力,这样TreeSet才知道按什么顺序存储对象。
Set中放入对象时需要重写equals方法来定义如何判断两个元素是否相同,其实Set的知识点还是很多的,本文主要面向参加蓝桥杯的同学,所以也不用过于深究,这里只介绍Set的简单使用~
HahSet
优点:
存取和查找性能特别好
缺点:
不能自动排序
与List中不同的方法已加粗
构造方法 依然推荐下面这种 通过接口来代替实例对象的方法
HashSet<Double> set = new HashSet<>();
Set<Double> set = new HashSet<>();
add() 添加元素
size() 方法
addAll(Collection<> c) 将另一个Collection集合的元素全部添加进来
remove(int index) 删除下标为index 的元素
contains(Object o) 判断是否含有该元素
contains(Collection c) 判断是否含有该集合中的元素(因为在Set集合中,所有元素不允许重复)
isEmpt() 判断集合是否为空
clear() 清空集合中所有元素
运行结果:
TreeSet
优点:
自动排序
可以存储对象,不局限于是Object下那几种数据类型
缺点:
如果想让TreeSet存储对象,需要继承Compareable接口并重写compareTo方法。
构造方法 同上 推荐下面这种
TreeSet<Double> set = new TreeSet<>();
Set<Double> set = new TreeSet<>();
其余方法和HashSet一致
遍历方式
toString() 已经写好了直接用就行了
加强for循环
注意:加强for循环的数据类型应该为包装类,即Integer、Double这种。
**迭代器 ** 这是List和HashSet所没有的
注意:迭代器不是new出来的,而是和Set接口创建HashSet一样,通过Iterator接口来代替对象实例化。
Iterator<Integer> iterator = set0.iterator(); while(iterator.hasNext()){ int temp = iterator.next(); System.out.print(temp+" "); }
运行结果:
Map
List与Set中的元素都是单个存储的,而Map中的元素是成对存储的,每个元素由键与值两部分组成,通过键可以找对所对应的值。
Map接口中最常用的实现类是HashMap,存储数据采用的哈希表结构,元素的存取顺序不能保证一致。
需要注意的是,Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值.
HashMap类
构造方法 同样,推荐第一种构造方式
HashMap<String,Integer> map = new HashMap<>();
Map<String, Integer> map = new HashMap<>();
put(<>key,<>val) 存放数据
get(Key key) 通过键得到键值
contains() 判断是否包含该键或值
containsKey(key) 判断是否包含该键
containsValue(val) 判断是否包含该值
replace(key ,val) 修改键对应的值
remove(key) 删除指定元素
keySet() 返回map所有键的Set集合
values() 返回map所有值的Collection集合
Set<<Map.Entry<k,v> entrySet() 返回map所有**键值对的Set集合**
很重要这个
Map.Entry<K,V>
是一个接口,**Map.entrySet()**方法返回地图的集合视图,其元素属于此类。
getKey() 获取键
getValue() 获取值
遍历方式
toString()
加强for循环
模糊版
System.out.println("输出所有人的名字: (键)"); for (String name:map.keySet()){ System.out.println(name); } System.out.println("输出所有年龄:(值)"); for (Integer age:map.values()){ System.out.println(age); }
清晰版
Set<String> names:map.keySet(); for (int name:names) { System.out.println(name); } Set<Integer> ages:map.values(); for (int age:ages) { System.out.println(age); }
entrySet() 拿到map的键和值的集合再遍历
T1.0 头大版本 通过接口来代替实例对象
HashMap<Integer,Integer> map = new HashMap(); //得到map的所有键的Set集合 Set<Map.Entry<Integer,Integer>> entrySet = map.entrySet(); //加强for循环遍历每一个键 for (Map.Entry<Character,Integer>entry:entrySet){ int value = entry.getValue(); char key = entry.getKey(); }
清爽版
for (Map.Entry<String, Integer> entry : map.entrySet()) { System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue()); }
迭代器
//为map的键的设置迭代器 输出所有名字 Iterator<String> iterator = map.keySet().iterator(); while (iterator.hasNext()){ String name = iterator.next(); System.out.print(name+" "); } System.out.println(); //用迭代器输出所有键对应的值 Iterator<Integer> iterator1 = map.values().iterator(); while (iterator1.hasNext()){ int age = iterator1.next(); System.out.print(age+" "); }
运行结果:
常用模型 - 记录某类型值出现的次数
实际案例
package Cup.API; import java.util.HashMap; import java.util.Map; //统计每个数字出现的次数 public class Test { public static void main(String[] args) { int[] arr = {5,5,2,2,5,7,4,2,9,8,1,2,3,5,4,7,8,9,6}; Map<Integer,Integer> map = new HashMap<>(); for (int i : arr) { if (!map.containsKey(i)) { map.put(i, 1); } else { int count = map.get(i); map.replace(i, ++count); } } //输出所有键各自对应的值 //用Map.Entry获取键值对 for (Map.Entry<Integer,Integer> entry: map.entrySet()){ System.out.println(entry.getKey()+"出现的次数为"+entry.getValue()); } } }
运行结果: