day_14~16:集合框架
集合
1.集合是Java API所提供的一系列类,可以用于动态存放多个对象。--》集合只能存对象
2.集合与数组的不同在于,集合是大小可变的序列,而且元素类型可以不受限制,只要是引用类型。(集合中不能放基本数据类型,但可以放基本数据类型的包装类)
3.集合类全部支持泛型,是一种数据安全的用法。
集合框架图
Java的集合框架从整体上可以分为两大家族:
1.Collection(接口)家族。该接口下的所有子孙均存储为单一对象。 Add(s)
2.Map(接口)家族。该接口下的所有子孙均存储的是key-value(键值对)形式的数据。 Put(key, value)
另外还有三个分支,均是为上述两个家族服务的。
1.Iterator(迭代器)家族。主要用于遍历Collection接口及其子类而设计。
2.Comparator(比较器),在集合中存储对象时候,用于对象之间的比较
3.Collections是工具类。注意该类带个s,一般就表示工具类。里面提供了N多静态方法,来对Collection集合进行操作。

Collection
List:有序(录入的顺序跟输出的顺序一致),可重复,存储单个元素 --》方法中添加了index参数,从 0 开始
ArrayList: 数据结构: 一维数组
LinkedList: 数据结构:双向链表
Vection: 数据结构:一维数组
Stack(继承Vector): 数据结构:一维数组 特点:栈的数据结构
ArrayList VS LinkedList (两个集合的使用方法一模一样)
区别:1.队列模式或栈模式就用LinkedList
2. ArrayList是实现了基于动态数组的数据结构,而LinkedList是基于链表的数据结构;
3.效率:
添加:一样快
插入:LinkedList快
删除:LinkedList快
查询:ArrayList快(因为ArrayList有下标)
ps:平时如果不用到队列模式(先进先出)或栈模式(先进后出)就用ArrayList,因为项目中往往查询比其他功能用的更频繁
Vector VS ArrayList
数据结构都是一维数组,但是Vector线程安全,ArrayList线程不安全
Set:无序(元素存入的顺序与取出的顺序不同,但是每次取出的顺序是一致的,无序不代表随机),不可重复
HashSet: 数据结构:Hash数组 应用场景:元素去重
TreeSet:
Map --- 集合(接口)
特点:键值对存储 K-V
HashMap: 数据结构:Hash数组 特点:key是唯一的,value可以重复
HashTable:
ConcurrentHashMap:
TreeMap:
List实现类之ArrayList
ArrayList和Array的区别:容量可扩展性、存储的必须是对象;
ArrayList的方法
一般情况newArrayList对象使用:ArrayList<E> array = new ArrayList<>(); 当我们需要用到List的其他实现类时就使用:List<E> list = new ArrayList<>();
public class Test { public static void main(String[] args) { ArrayList<Object> list = new ArrayList<>(); //添加元素 list.add("赤名莉香"); list.add("关口里美"); list.add("长崎尚子"); list.add("赤名莉香"); list.add("永尾完治"); list.add("三上健一"); list.add("赤名莉香"); System.out.println("获取第一个元素:"+list.get(0)); System.out.println("获取该集合长度:"+list.size()); System.out.println("判断集合内是否有指定元素:"+list.contains("赤名莉香")); System.out.println("集合内没有元素吗?"+list.isEmpty()); System.out.println("查询置顶元素在集合中第一次出现的位置:"+list.indexOf("赤名莉香")); System.out.println("查询指定元素在集合中最后一次出现的位置:"+list.lastIndexOf("赤名莉香")); //替换 list.set(3, "和贺夏树"); //插入 list.add(3, "渡边"); //删除 list.remove(1); //遍历--for for(int i=0;i<list.size();i++) { System.out.println(list.get(i)); } System.out.println("----------------------"); //遍历--foreach for (Object object : list) { System.out.println(object); } System.out.println("----------------------"); //遍历--迭代器 Iterator<Object> iterator = list.iterator(); while(iterator.hasNext()) { System.out.println(iterator.next()); } } }
public class Test03 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("赤名莉香"); list.add("关口里美"); list.add("长崎尚子"); list.add("赤名莉香"); list.add("永尾完治"); list.add("三上健一"); list.add("赤名莉香"); // 遍历删除 Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String string = iterator.next(); if (string.equals("关口里美")) { iterator.remove();// 删除指定指针 } } for (String string : list) { System.out.println(string); } } }
public class Test04 { public static void main(String[] args) { //特殊点: ArrayList<Integer> list = new ArrayList<>(); //自动装箱 list.add(1);//list.add(Integer.valueOf(1)); list.add(2); list.add(3); list.add(4); //以元素删除 --- 手动装箱 list.remove(Integer.valueOf(2)); Iterator<Integer> it = list.iterator(); while (it.hasNext()) { Integer integer = it.next(); System.out.println(integer); } } }
List实现类之LinkedList
与ArrayList的用法一模一样,多了队列模式和栈模式
public class Test01 { public static void main(String[] args) { /** * 队列模式:先进先出 */ LinkedList<String> list = new LinkedList<>(); list.add("赤名莉香1"); list.add("赤名莉香2"); list.add("赤名莉香3"); list.add("赤名莉香4"); while(!list.isEmpty()) { //删除列表中的第一个元素,并返回 String removeFirst = list.removeFirst(); System.out.println(removeFirst); } } }
public class Test02 { public static void main(String[] args) { /** * 栈模式:先进后出 */ LinkedList<String> list = new LinkedList<>(); list.add("赤名莉香1"); list.add("赤名莉香2"); list.add("赤名莉香3"); list.add("赤名莉香4"); while(!list.isEmpty()) { //删除列表中的最后一个元素,并返回 String removeFirst = list.removeLast(); System.out.println(removeFirst); } } }
LinkedList源码分析
分析源码: 1.找入口 2.看主线 -----------------------LinkedList.class------------------------- 廖佳星 夏凡 舒老师 transient Node<E> first; transient Node<E> last; public boolean add(E e) { linkLast(e); return true; } void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; } -----------------------LinkedList$Node.class------------------------- private static class Node<E> { E item; ----- 元素 Node<E> next; --- 下一个节点的地址 Node<E> prev; --- 上一个节点的地址 Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }
List实现类之Vector
public class Test02 { public static void main(String[] args) { Vector<String> vector = new Vector<>(); vector.addElement("麻生希1"); vector.addElement("麻生希2"); vector.addElement("麻生希3"); vector.addElement("麻生希4"); vector.setElementAt("桃谷绘里香", 1); vector.removeElement("麻生希3"); vector.removeElementAt(2); Enumeration<String> elements = vector.elements(); while(elements.hasMoreElements()){ String nextElement = elements.nextElement(); System.out.println(nextElement); } } }
List实现类之Stack
public class Test01 { public static void main(String[] args) { Stack<String> stack = new Stack<>(); //把项压入栈顶(添加) stack.push("夏凡1"); stack.push("夏凡2"); stack.push("夏凡3"); stack.push("夏凡4"); //遍历 while(!stack.empty()){ String pop = stack.pop(); System.out.println(pop); } } }
Map实现类之HashMap
HashMap的方法
public class Test01 { public static void main(String[] args) { HashMap<String, Integer> map = new HashMap<>(); //添加 map.put("麻生希", 23); map.put("天海翼", 26); map.put("小泽玛利亚", 28); map.put("泷泽萝拉", 21); map.put("北川瞳", 27); //替换 map.put("泷泽萝拉", 888); //删除(通过key删除映射关系) map.remove("北川瞳"); System.out.println("通过key获取到指定的值:" + map.get("天海翼")); System.out.println("判断此集合是否有指定key:" + map.containsKey("天海翼")); System.out.println("判断此集合是否有指定value:" + map.containsValue(21)); System.out.println("判断此集合中是否没有元素:" + map.isEmpty()); System.out.println("获取此集合中映射关系的个数为:" + map.size()); //遍历思路一:把map集合中的所有key取出放在set集合里,遍历set集合依次取出key,就可以取出key对应的value Set<String> keySet = map.keySet(); for (String key : keySet) { Integer value = map.get(key); System.out.println(key + " -- " + value); } System.out.println("---------------------"); //遍历思路二:把map集合中的所有“映射关系”取出放在set集合里 //(映射关系就是Entry类的对象,对象中有两个重要属性:key、value) Set<Entry<String, Integer>> entrySet = map.entrySet(); for (Entry<String, Integer> entry : entrySet) { String key = entry.getKey(); Integer value = entry.getValue(); System.out.println(key + " -- " + value); } } }
判断一个字符串里字符出现的次数
public class Test03 { public static void main(String[] args) { //判断一个字符串里字符出现的次数??? String str = "123123abcdcdefg12"; char[] charArray = str.toCharArray(); HashMap<Character, Integer> map = new HashMap<>(); for (char c : charArray) { if(map.get(c) == null){ map.put(c, 1); }else{ map.put(c, map.get(c)+1); } } Set<Entry<Character,Integer>> entrySet = map.entrySet(); for (Entry<Character, Integer> entry : entrySet) { Character key = entry.getKey(); Integer value = entry.getValue(); System.out.println(key + " -- " + value); } /** * 思考题:HashSet底层由HashMap实现, * HashSet是存一个值,HashMap是存两个值 * 结合两个集合的特点,分析出HashSet存值是存在底层的HashMap里的key还是value的位置?? */ } }
Set实现类之HashSet
方法和HashMap一样
Set实现类之TreeSet
TreeSet常用方法及Integer类型排序:数字升序
public class Test01 { public static void main(String[] args) { /** * TreeSet存入Integer类型排序规则是:数字升序 */ TreeSet<Integer> set = new TreeSet<>(); set.add(2); set.add(1); set.add(4); set.add(3); System.out.println("判断此集合是否有指定元素:" + set.contains(2)); System.out.println("判断此集合是否没有元素:" + set.isEmpty()); System.out.println("获取此集合元素的个数:" + set.size()); set.remove(3); //遍历 : foreach for (Integer integer : set) { System.out.println(integer); } System.out.println("-------------------"); //遍历:迭代器 Iterator<Integer> it = set.iterator(); while (it.hasNext()) { Integer integer = (Integer) it.next(); System.out.println(integer); } } }
TreeSet存入String类型排序:字典排序
public class Test02 { public static void main(String[] args) { /** * TreeSet存入String类型排序规则是:字典排序 */ TreeSet<String> set = new TreeSet<>(); set.add("c"); set.add("a"); set.add("cd"); set.add("dd"); set.add("dd"); for (String string : set) { System.out.println(string); } } }
实现Comparable接口的排序
public class Student implements Comparable<Student>{ private String name; private int age; private char sex; private String classId; private String id; @Override public int compareTo(Student o) {//排序规则:按年龄排序 // if(this.age > o.age){ // return 1; // }else if(this.age < o.age){ // return -1; // }else{ // return 0; // } return this.age - o.age; } public Student() { } public Student(String name, int age, char sex, String classId, String id) { this.name = name; this.age = age; this.sex = sex; this.classId = classId; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } public String getClassId() { return classId; } public void setClassId(String classId) { this.classId = classId; } public String getId() { return id; } public void setId(String id) { this.id = id; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((classId == null) ? 0 : classId.hashCode()); result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (classId == null) { if (other.classId != null) return false; } else if (!classId.equals(other.classId)) return false; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + ", sex=" + sex + ", classId=" + classId + ", id=" + id + "]"; } }
public class Test03 { public static void main(String[] args) { TreeSet<Student> set = new TreeSet<>(); set.add(new Student("麻生希", 27, '女', "1807", "001")); set.add(new Student("小西满里惠", 27, '女', "1807", "002")); set.add(new Student("泷泽萝拉", 23, '女', "1807", "003")); set.add(new Student("铃原爱蜜莉", 21, '女', "1807", "004")); set.add(new Student("北条麻衣", 39, '女', "1807", "005")); set.add(new Student("夏凡", 27, '男', "1807", "006")); for (Student stu : set) { System.out.println(stu); } } }
创建TreeSet时,传入Comparator的实现类的对象实现排序
public class Test04 { public static void main(String[] args) { TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) {//重新编写排序规则:按照名字长度排序,长度一致按年龄排序,重复学生不能存入TreeSet集合里 if(o1.equals(o2)){//判断对象是否相同(判断classId和id) return 0; } if(o1.getName().length() != o2.getName().length()){//名字长度不一致 return o1.getName().length() - o2.getName().length(); }else{ if(o1.getAge() != o2.getAge()){ return o1.getAge() - o2.getAge(); }else{ return 1; } } } }); set.add(new Student("麻生希", 27, '女', "1807", "001")); set.add(new Student("小西满里惠", 27, '女', "1807", "002")); set.add(new Student("泷泽萝拉", 23, '女', "1807", "003")); set.add(new Student("铃原爱蜜莉", 21, '女', "1807", "004")); set.add(new Student("北条麻衣", 39, '女', "1807", "005")); set.add(new Student("夏凡", 27, '男', "1807", "006")); set.add(new Student("夏凡", 27, '男', "1807", "007")); for (Student stu : set) { System.out.println(stu); } } }
Map实现类之TreeMap
基本方法
public class Test01 { public static void main(String[] args) { //排序遵循了Integer的排序规则 TreeMap<Integer, String> map = new TreeMap<>(); map.put(27, "小西满里惠"); map.put(23, "杨程"); map.put(21, "铃原爱蜜莉"); map.put(32, "北条麻衣"); map.put(28, "夏凡"); map.put(18, "贾玲"); //替换 map.put(18, "舒玲"); //删除(通过key删除映射关系) map.remove(28); System.out.println("通过key获取到指定的值:" + map.get(18)); System.out.println("判断此集合是否有指定key:" + map.containsKey(18)); System.out.println("判断此集合是否有指定value:" + map.containsValue("杨程")); System.out.println("判断此集合中是否没有元素:" + map.isEmpty()); System.out.println("获取此集合中映射关系的个数为:" + map.size()); //遍历:keySet 不适用:因为二叉树的数据结构,会使得数据丢失 Set<Integer> set = map.keySet(); for (Integer key : set) { String value = map.get(key); System.out.println(key + " --- " + value); } System.out.println(" ------------- "); //遍历:entrySet Set<Entry<Integer,String>> entrySet = map.entrySet(); for (Entry<Integer, String> entry : entrySet) { Integer key = entry.getKey(); String value = entry.getValue(); System.out.println(key + " --- " + value); } } }
Comparator接口的实现类(匿名内部类)的排序规则
public class Test02 { public static void main(String[] args) { //排序遵循了Comparator接口的实现类(匿名内部类)的排序规则 TreeMap<Integer, String> map = new TreeMap<>(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2-o1; } }); map.put(27, "小西满里惠"); map.put(23, "杨程"); map.put(21, "铃原爱蜜莉"); map.put(32, "北条麻衣"); map.put(28, "夏凡"); map.put(18, "贾玲"); //替换 map.put(18, "舒玲"); //删除(通过key删除映射关系) map.remove(28); System.out.println("通过key获取到指定的值:" + map.get(18)); System.out.println("判断此集合是否有指定key:" + map.containsKey(18)); System.out.println("判断此集合是否有指定value:" + map.containsValue("杨程")); System.out.println("判断此集合中是否没有元素:" + map.isEmpty()); System.out.println("获取此集合中映射关系的个数为:" + map.size()); //遍历:keySet 不适用:因为二叉树的数据结构,会使得数据丢失 Set<Integer> set = map.keySet(); for (Integer key : set) { String value = map.get(key); System.out.println(key + " --- " + value); } System.out.println(" ------------- "); //遍历:entrySet Set<Entry<Integer,String>> entrySet = map.entrySet(); for (Entry<Integer, String> entry : entrySet) { Integer key = entry.getKey(); String value = entry.getValue(); System.out.println(key + " --- " + value); } } }
集合总结
学习路线:基本使用 -> 做实验 -> 画图 -> 分析底层源码 集合:数据的容器(类似于数组) 1.Collection --- 集合(接口) List -- 接口(添加了对于下标进行操作的方法) 特点:有序,且可重复的 ArrayList: 数据结构:一维数组 应用场景:存储数据 LinkedList: 数据结构:双向链表 应用场景:存储数据、队列模式、栈模式 Vector: 数据结构:一维数组 Stack:(继承Vector) 数据结构:一维数组 特点:栈的数据结构 Set -- 接口 特点:无序,且不可重复 HashSet: 数据结构:Hash数组 应用场景:元素去重 TreeSet: 数据结构:二叉树 应用场景:自然排序 ps:TreeSet存入元素是存到TreeMap集合中key的位置 2.Map --- 集合(接口) 特点:键值对存储 K-V HashMap: 数据结构:Hash数组 特点:key是唯一的,value可以重复 HashTable: 数据结构:Hash数组 ConcurrentHashMap: 数据结构:Segment数组 特点:分段式加锁 TreeMap: 数据结构:二叉树 应用场景:自然排序(对key进行排序) 注意: 1.理解无序: 无序是指:存入元素的顺序与取出元素的顺序不一致,无序不代表随机 2.Collection 与 Map的区别? Collection存储单个元素 Map存储两个元素 3.ArrayList vs LinkedList(两个集合的使用方法一模一样) 区别: 1.队列模式或栈模式就用LinkedList 2.效率: 添加:一样快 插入:LinkedList快 删除:LinkedList快 查询:ArrayList快 ps:平时如果不用到队列模式或栈模式就用ArrayList,因为项目中往往查询比其他功能用的频繁 4.Vector vs ArrayList 数据结构都是一维数组,但Vector-线程安全 ,ArrayList-线程不安全的 5.HashMap vs Hashtable vs ComcurrenHashMap (使用方式一模一样) 区别: 1.HashMap可以存放null值,其他两个集合不可以存放null值 2.HashMap线程不安全 Hashtable线程安全 ComcurrenHashMap线程安全 6.Hashtable vs ComcurrenHashMap Hashtable:方法里加锁 ComcurrenHashMap:Segment对象中加锁,又叫做分段式加锁 ps:分段式加锁要比方法里加锁的效率更好 7.TreeSet特点是排序,请问排序规则的代码是写在哪个地方的?? TreeSet --- Integer : 数字升序 TreeSet --- String : 字典排序 答:排序规则写在存入元素所属类里 8.Comparable、Comparator排序接口 Comparable排序接口:一个类的对象要存入TreeSet里,这个对象所属类就必须实现此接口里的compareTo排序方法 Comparator排序接口:元素所属的类是别人提供的,又想改变排序规则,就在创建TreeSet时,传入Comparator的实现类的对象(一般使用匿名内部类) 调用的优先级别:Comparator > Comparable




浙公网安备 33010602011771号