赞
踩
前提:栈、堆、二叉树、hashcode、toString()、quesalus()的知识深入和底层理解。
集合就是咋们所说的容器 前面我们学习过数组 数组也是容器 容器:装东西的 生活中有多少的容器呀? 水杯 教室 酒瓶 水库 只要是能装东西的 都可以看成是容器 我们这个集合的容器 是用来装啥的呢? 装数据? 数据? 一切可以被计算机识别的 文字 图片 视频 音频都是数据 说白了 我们今天所学习的这个集合 就跟前面的数组类似 只是底层的实现不一样而已
主要根据我们的值的个数 可以分成 单例集合 和 双列集合 单例集合:简单的说 在这个容器中存放的的值 就是一个一个的 value 单列集合的爹:Collection 双列集合:他在容器中存储的数据就是 键值对 key---value 双列集合的爹:Map
ArrayList<E> 这个集合中的泛型:表示的意思其实就是对这个容器中能存放数据类型的一种约束 比如我们的泛型的数据类型是:User 那么这个容器中只能存放User类型的数据 这个ArrayList底层就是数组 他是有序的 地址空间是连续的 地址空间连续 就意味着能通过开始地址+偏移量来为访问 而且能重复添加数据 有序:一定能通过下标访问数据 List中所有的内容都是可以重复的....
public class ArrayListTest { public static void main(String[] args) { //第一种方式 List<String> list = new ArrayList<>(); //接下来就可以向这个集合中存放数据了... list.add("123"); list.add("456"); list.add("789"); list.add("789"); List<String> list2 = new ArrayList<>(); //接下来就可以向这个集合中存放数据了... list.add("12322"); list.add("45622"); //将list2集合中的数据 添加到 list中来 list.addAll(list2); //能不能删除数据呢? //这个就是直接删除某一个元素 list.remove("789"); //还可以通过下标删除 list.remove(0); //接下来玩下修改呢? list.set(0,"小波波"); //获取某一个位置的元素 String s = list.get(0); //判断这个集合中是否存在某一个元素 boolean contains = list.contains("789"); //判断集合是否为空 boolean empty = list.isEmpty(); //返货某一个元素的下标位置 int i = list.indexOf("789"); //截取集合中指定位置的元素 生成一个新的集合 List<String> stringList = list.subList(0, 5); System.out.println("list集合的size:"+list.size()); List<User> userList=new ArrayList<>(); userList.add(new User(1,"小小","123")); userList.add(0,new User(0,"这里是测试","xxx")); System.out.println("userList集合的size:"+userList.size()); System.out.println("userList中的数据是:"+userList.get(0)); } }
public class ArrayListTest1 { public static void main(String[] args) { List<String> list = new ArrayList<>(); //接下来就可以向这个集合中存放数据了... list.add("123"); list.add("456"); list.add("789"); list.add("789"); //第一种遍历方式:因为这个ArrayList本身底层是数组(Object类型的数组) 数组地址空间连续 所以我们能通过下标来访问 for (int i = 0; i <list.size() ; i++) { System.out.println("集合中的值:"+list.get(i)); } System.out.println("------------------------------"); //第二种遍历方式 通过增强的for循环来玩 for (String val:list){ System.out.println("集合中的值:"+val); } System.out.println("------------------------------"); //第三种遍历方式通过JDK8中的stream流来遍历 list.stream().forEach(val->{ System.out.println("集合中的值:"+val); }); System.out.println("------------------------------"); //第四种遍历方式:迭代器 迭代器的游标问题 /** * 这种情况下不允许对元素进行修改和删除 * * 其实不止是这种情况 在遍历的情况下 逻辑上都允许修改和删除的产生 */ Iterator<String> it = list.iterator(); // it.hasNext():判断下一个节点是否有元素 while (it.hasNext()){ // it.next() :取出当前位置的元素 String val = it.next(); System.out.println("通过迭代器取出来的值:"+val); } System.out.println("------------------------------"); //第五种遍历方式 ListIterator<String> it1 = list.listIterator(); while (it1.hasNext()){ String next = it1.next(); System.out.println("通过迭代器取出来的值:"+next); } } }
LinkedList底层是链表 链表中包含 一个一个的链条 每一个链条都包含了两部分 当前节点的值 和 下一个元素的地址 链表中 数据存储的地址空间不连续 所以不能使用偏移量来访问
输出的值是连续的。
public class LinkedListTest01 { public static void main(String[] args) { //申明对象 List<String> linkedList1 = new LinkedList<>(); linkedList1.add("001"); linkedList1.add("002"); linkedList1.add("003"); linkedList1.add("004"); for (int i = 0; i < linkedList1.size(); i++) { String val = linkedList1.get(i); System.out.println("val:"+val); } for (String val:linkedList1){ System.out.println("val:"+val); } linkedList1.stream().forEach(val->{ System.out.println("val:"+val); }); } }
这个底层也是数组 线程安全的 效率不高 这个集合基本不使用 不也用记住
public class VectorTest { public static void main(String[] args){ List<String> vector=new Vector<>(); vector.add("中国好"); vector.add("小日子"); for (int i = 0; i <vector.size() ; i++) { System.out.println("数据是:"+vector.get(i)); } } }
public class StackTest { public static void main(String[] args){ //这个其实是栈的数据结构 Stack<String> list=new Stack<String>(); list.push("1"); list.push("2"); list.push("3"); list.push("4"); list.push("5"); System.out.println("pop:"+list.pop()); System.out.println("pop:"+list.pop()); System.out.println("pop:"+list.pop()); System.out.println("pop:"+list.pop()); System.out.println("pop:"+list.pop()); } }
逻辑上 Set集合逻辑上是无序的 而且Set集合能排重 不能通过下标直接访问 Set<E> 的爹 依然是Collection Set这个接口是所有Set集合的爹 Set排重的原则是啥? 如果在Set集合中存放的是对象比如User 那么他就首先会去调用这个User中的 hashCode方法 然后获取到当前的这个要添加数据的hashCode值去和已经添加数据的HashCode值 做比较 如果是不等 那么说明肯定不是一个元素 那么直接添加元素 如果是HashCode值 遇到了在已经添加的数据中的HashCode值是相等的话 那么都说明有可能这个值是重复的 如果是这个值是重复的话 那就去调用当前这个对象的equals方法 判断equals方法是不是返回true 如果返回true 那么说明值重复 不添加数据 如果返回的是false 那么说明值 不重复 那么就可以添加数据
public static void main(String[] args) { Set<String> set = new HashSet<>(); set.add("123"); set.add("345"); set.add("234"); set.add("345"); System.out.println("数据的个数:" + set.size()); System.out.println("-----------------------------"); Set<User> setUser = new HashSet<>(); setUser.add(new User(1, "小小", "112")); setUser.add(new User(1, "小小", "134")); setUser.add(new User(1, "小小", "165")); setUser.add(new User(1, "小小", "178")); System.out.println("数据的个数:" + setUser.size()); }
public class User { private Integer id; private String username; private String password; public User(Integer id, String username, String password) { this.id = id; this.username = username; this.password = password; } public User() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public int hashCode() { return this.username.hashCode(); } /** * 用户名一样 那么我们就认为这是同一个数据 * @param obj * @return */ @Override public boolean equals(Object obj) { if(obj instanceof User){ User user= (User) obj; return this.username.equals(user.getUsername()); } return false; } }
public class HashSetTest1 { public static void main(String[] args) { Set<User> set = new HashSet<>(); set.add(new User(1,"xiaobobo","123")); set.add(new User(-1,"tiedan","777")); set.add(new User(3,"gousheng","0")); set.add(new User(4,"gouwa","234")); set.add(new User(1,"ergouzi","234")); //通过增强的for循环能访问 for (User val:set){ System.out.println("数据:"+val); } System.out.println("--------------------------"); Iterator<User> it = set.iterator(); while (it.hasNext()){ User next = it.next(); System.out.println("拿到的数据是:"+next); } System.out.println("--------------"); set.stream().forEach(user -> { System.out.println("读取到的数据是:"+user); }); } }
这个集合的底层是链表 这个集合的数据保存是有序的
public class LinkedHashSetTest { public static void main(String[] args) { Set<User> set = new LinkedHashSet<>(); set.add(new User(1, "xiaobobo", "123")); set.add(new User(-1, "tiedan", "777")); set.add(new User(3, "gousheng", "0")); set.add(new User(4, "gouwa", "234")); set.add(new User(1, "gouwa", "234")); Iterator<User> it = set.iterator(); while (it.hasNext()) { User next = it.next(); System.out.println(next); } } }
TreeSet和其他的Set集合一样 具有 排重的特性 TreeSet的底层是红黑树--->二叉树--->数据结构--->有大小关系 TreeSet集合自动具有排序的功能 这个排序 就涉及到一个大小的问题 自然数的大小 字符串如何比较大小呢? unicode编码值
// 在String这个类中为我们提供了这个比较两个字符串大小的方法 public static void main(String[] args) { String str = "Ab"; String str2 = "Ab"; /** * 返回值 0:表示的是前后相等 * 返回值-1:表示的是前面小于后面 * 返回值是1:表示的是前面大于后面 */ System.out.println(str2.compareTo(str)); }
TreeSet的底层使用的是红黑树来实现的
package com.qfedu.edu.collection.set; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; public class TreeSetTest { public static void main(String[] args) { Set<Integer> set = new TreeSet<>(); set.add(123); set.add(0); set.add(345); set.add(77); set.add(77); set.add(89); //遍历这些数据 Iterator<Integer> it = set.iterator(); while (it.hasNext()) { Integer next = it.next(); System.out.println("数据是:" + next); } //--------------下面研究字符串的排序------------ System.out.println("-------------------"); Set<String> setStr = new TreeSet<>(); setStr.add("Abc"); setStr.add("Bc"); setStr.add("Ac"); //遍历这些数据 Iterator<String> it1 = setStr.iterator(); while (it1.hasNext()) { String next = it1.next(); System.out.println("数据是:" + next); } } }
1、编写Employee对象
public class Employee implements Comparable<Employee>{ private Integer id; private String name; private Integer salary; private String address; public Employee(Integer id, String name, Integer salary, String address) { this.id = id; this.name = name; this.salary = salary; this.address = address; } public Employee() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getSalary() { return salary; } public void setSalary(Integer salary) { this.salary = salary; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } /** * 比较的方法 * 你需要按照谁排序 那么下面你就按照什么来比较 * * 我要通过薪资排序 * 薪资是int类型 那么下面就直接做减法 * @param o the object to be compared. * @return */ // @Override // public int compareTo(Employee o) { // return this.salary-o.getSalary(); // } /** * 下面演示通过姓名来排序 * 姓名是字符串类型 * @param o the object to be compared. * @return */ /* @Override public int compareTo(Employee o) { return this.getName().compareTo(o.getName()); }*/ /** * 如果薪资不为空 那么按照薪资排序 * 如果薪资为空 并且姓名不为空 那么按照姓名排序 * 如果姓名为空 那么就按照id排序.... * @param o the object to be compared. * @return */ @Override public int compareTo(Employee o) { if(o.getSalary()!=null){ return this.getSalary()-o.getSalary(); }else if(o.getName()!=null&&!("".equals(o.getName()))){ return this.getName().compareTo(o.getName()); }else{ return this.id-o.getId(); } } @Override public String toString() { return "Employee{" + "id=" + id + ", name='" + name + '\'' + ", salary=" + salary + ", address='" + address + '\'' + '}'; } }
2、编写测试类
public class TreeSetTest1 { public static void main(String[] args) { Set<Employee> set = new TreeSet<>(); set.add(new Employee(1,"xiaobobo",3500,"四川成都")); set.add(new Employee(2,"xiaowangzi",1800,"四川巴中")); set.add(new Employee(3,"tiedan",2600,"四川自贡")); set.add(new Employee(4,"gousheng",15000,"四川绵阳")); set.add(new Employee(5,"gouwa",2700,"四川德阳")); Iterator<Employee> iterator = set.iterator(); while (iterator.hasNext()){ Employee next = iterator.next(); System.out.println("获取到的数据是:"+next); } } }
1、对象的编写
public class Employee1{ private Integer id; private String name; private Integer salary; private String address; public Employee1(Integer id, String name, Integer salary, String address) { this.id = id; this.name = name; this.salary = salary; this.address = address; } public Employee1() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getSalary() { return salary; } public void setSalary(Integer salary) { this.salary = salary; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Employee{" + "id=" + id + ", name='" + name + '\'' + ", salary=" + salary + ", address='" + address + '\'' + '}'; } }
2、测试的编写
package com.qfedu.edu.collection.set; import com.qfedu.edu.pojo.Employee; import com.qfedu.edu.pojo.Employee1; import java.util.Comparator; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; /** * @author xiaobobo * @title: TreeSetTest * @projectName CD-Java-JY-2401-Simple-Parent * @description: 这个研究下TreeSet的对象的排序问题 * @date 2024/3/19 15:26 */ public class TreeSetTest2 { public static void main(String[] args) { Set<Employee1> set = new TreeSet<>(new MyComparator()); set.add(new Employee1(1,"xiaobobo",3500,"四川成都")); set.add(new Employee1(2,"xiaowangzi",1800,"四川巴中")); set.add(new Employee1(3,"tiedan",2600,"四川自贡")); set.add(new Employee1(4,"gousheng",15000,"四川绵阳")); set.add(new Employee1(5,"gouwa",2700,"四川德阳")); Iterator<Employee1> iterator = set.iterator(); while (iterator.hasNext()){ Employee1 next = iterator.next(); System.out.println("获取到的数据是:"+next); } } /** * 自定义了一个比较器 这个跟上一个接口是一样的 */ static class MyComparator implements Comparator<Employee1>{ /** * * @param o1 新数据 * @param o2 老数据 * 按照薪资排序 做减法 按照谁排序 就用谁来做比较 * @return */ @Override public int compare(Employee1 o1, Employee1 o2) { return o1.getSalary()-o2.getSalary(); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。