java进阶——day03-2 List、Set、数据结构、Collections
List集合
简介
List接口继承Collection接口,是单列集合的一个重要分支,通常会将实现类List接口的对象称为List集合。
特点
1、List集合中允许出现重复的元素,通过equals方法,来比较是否为重复的元素。
2、List集合是一个元素存取有序的集合。例如存的元素是22、11、33,。那么在集合中,元素的存储就是按照22、11、33顺序完成的。
package day03_1; import java.util.ArrayList; import java.util.List; public class List_demo01 { public static void main(String[] args) { List<Integer> list_arr = new ArrayList<>(); list_arr.add(5); list_arr.add(4); list_arr.add(7); list_arr.add(3); System.out.println(list_arr);//[5, 4, 7, 3] } }
3、List集合是一个带有索引的集合,通过索引可以精确的操作集合中的元素(与数组的索引是一个道理)
List接口中常用方法
List集合作为Collection集合的子接口,不但继承了Collection集合中的全部方法,还增加了根据元素索引老操作集合的方法。
public void add(int index,E element):将指定元素,添加到该集合的指定位置
package day03_1; import java.util.ArrayList; import java.util.List; public class List_demo { public static void main(String[] args) { List<String> list = new ArrayList<>(); //往 List集合 添加元素 list.add("喜羊羊"); list.add("懒羊羊"); list.add("灰太狼"); System.out.println(list);//[喜羊羊, 懒羊羊, 灰太狼] //指定位置添加元素 list.add(1,"小灰灰"); System.out.println(list);//[喜羊羊, 小灰灰, 懒羊羊, 灰太狼] } }
public E get(int index):获取集合指定位置元素
package day03_1; import java.util.ArrayList; import java.util.List; public class List_demo { public static void main(String[] args) { List<String> list = new ArrayList<>(); //往 List集合 添加元素 list.add("喜羊羊"); list.add("懒羊羊"); list.add("灰太狼"); System.out.println(list);//[喜羊羊, 懒羊羊, 灰太狼] //指定位置添加元素 list.add(1,"小灰灰"); System.out.println(list);//[喜羊羊, 小灰灰, 懒羊羊, 灰太狼] String who = list.get(2); System.out.println(who);//懒羊羊 } }
public E remove(int index):移除集合中指定位置的元素,返回的是被移除的元素?
package day03_1; import java.util.ArrayList; import java.util.List; public class List_demo { public static void main(String[] args) { List<String> list = new ArrayList<>(); //往 List集合 添加元素 list.add("喜羊羊"); list.add("懒羊羊"); list.add("灰太狼"); System.out.println(list);//[喜羊羊, 懒羊羊, 灰太狼] //指定位置添加元素 list.add(1,"小灰灰"); System.out.println(list);//[喜羊羊, 小灰灰, 懒羊羊, 灰太狼] String who = list.get(2); System.out.println(who);//懒羊羊 String del = list.remove(0); System.out.println(del);//喜羊羊 } }
public E set(int index,E element):用指定元素 替换 指定位置的元素,返回值是更新前的元素
package day03_1; import java.util.ArrayList; import java.util.List; public class List_demo { public static void main(String[] args) { List<String> list = new ArrayList<>(); //往 List集合 添加元素 list.add("喜羊羊"); list.add("懒羊羊"); list.add("灰太狼"); System.out.println(list);//[喜羊羊, 懒羊羊, 灰太狼] //指定位置添加元素 list.add(1,"小灰灰"); System.out.println(list);//[喜羊羊, 小灰灰, 懒羊羊, 灰太狼] String who = list.get(2); System.out.println(who);//懒羊羊 System.out.println(list); // String del = list.remove(0); // System.out.println(del);//喜羊羊 String setWho = list.set(1, "红太狼"); System.out.println(setWho);//小灰灰 System.out.println(list);//[喜羊羊, 红太狼, 懒羊羊, 灰太狼] } }
List的子类
ArrayList集合
ArrayList集合存储的数据结构是数组结构。元素增删慢、查询快,由于日常开发中使用最多的功能为查询、遍历数组,所以ArrayList是最常用的集合。
许多程序员开发时,非常随意的使用ArrayList完成需求,不提倡不严谨的用法。
LinkedList集合
LinkedList集合存储数据的结构是链表结构。是便于元素添加、删除的集合。
LinkedList是双向链表:

常用方法
// LinkedList是List集合的子类,List中的方法LinkedList都是可以使用,所以只演示LinkedList特有的方法
public void addFirst(E element):将指定元素插入此列表的开头
package day03_1; import java.util.LinkedList; public class Linked_List { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("北大"); linkedList.addFirst("清华"); System.out.println(linkedList);//[清华, 北大] } }
public void addList(E element):将指定元素插入此列表尾部
package day03_1; import java.util.LinkedList; public class Linked_List { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("北大"); linkedList.addFirst("清华"); linkedList.addLast("黎明职业大学"); System.out.println(linkedList);//[清华, 北大, 黎明职业大学] } }
public E getFirst():返回此列表中的第一个元素
package day03_1; import java.util.LinkedList; public class Linked_List { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("北大"); linkedList.addFirst("清华"); linkedList.addLast("黎明职业大学"); String first = linkedList.getFirst(); System.out.println(first);//清华 } }
public E getLast():返回此列表最后一个元素
package day03_1; import java.util.LinkedList; public class Linked_List { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("北大"); linkedList.addFirst("清华"); linkedList.addLast("黎明职业大学"); String last = linkedList.getLast(); System.out.println(last);//黎明职业大学 } }
public E removeFirst():移除此列表中的第一个元素,并元素删除元素
package day03_1; import java.util.LinkedList; public class Linked_List { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("北大"); linkedList.addFirst("清华"); linkedList.addLast("黎明职业大学"); String s = linkedList.removeFirst(); System.out.println(s);//清华 } }
public E removeLast():移除此列表中的最后一个元素,并返回移除元素
package day03_1; import java.util.LinkedList; public class Linked_List { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("北大"); linkedList.addFirst("清华"); linkedList.addLast("黎明职业大学"); String s = linkedList.removeLast(); System.out.println(s);//黎明职业大学 } }
public E pop():从此列表所表示的堆栈中弹出一个元素。
package day03_1; import java.util.LinkedList; public class Linked_List { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("北大"); linkedList.addFirst("清华"); linkedList.addLast("黎明职业大学"); String pop = linkedList.pop(); System.out.println(pop);//清华 } }
pubulic void push(E e):将元素推入此列表表示的堆栈
package day03_1; import java.util.LinkedList; public class Linked_List { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("北大"); linkedList.addFirst("清华"); linkedList.addLast("黎明职业大学"); linkedList.push("厦大"); System.out.println(linkedList);//[厦大, 清华, 北大, 黎明职业大学] } }
public boolean isEmpty():判断集合是否为空,布尔类型返回值
package day03_1; import java.util.LinkedList; public class Linked_List { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("北大"); linkedList.addFirst("清华"); linkedList.addLast("黎明职业大学"); boolean empty = linkedList.isEmpty(); System.out.println(empty);//false } }
set接口
Set接口和List接口一样,同样继承Collection接口,它与Collection接口的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格了,与List接口不同的是,Set接口中元素无序,并且会以某种规则保证存入的元素不重复。
注意:Set集合取出元素的方式,可采用:迭代器、增强for
Set子类--HashSet集合
概述
HashSet是Set接口的一个实现类,它存储的元素不可重复,且索引元素都是无序的(即存取顺序不一致)。
HashSet是根据对象的哈希值来确定元素在集合中的存储位置,具有良好的存取和查找性能。
保证元素的唯一性,依赖于:HashCode()方法和equals()方法。
package day03_1; import java.util.HashSet; public class Hash_Set { public static void main(String[] args) { HashSet<Integer> hash = new HashSet<>(); hash.add(5); hash.add(3); hash.add(7); hash.add(1); System.out.println(hash);//[1, 3, 5, 7] } }
package day03_1; import java.util.HashSet; public class Hash_Set { public static void main(String[] args) { HashSet<Integer> hash = new HashSet<>(); hash.add(5); hash.add(3); hash.add(7); hash.add(1); System.out.println(hash);//[1, 3, 5, 7] hash.add(1); System.out.println(hash);//[1, 3, 5, 7] } }
//当再次存入相同数据时,类似被覆盖了~
使用迭代器和增强for输出
package day03_1; import java.util.HashSet; import java.util.Iterator; public class Hash_Set { public static void main(String[] args) { HashSet<Integer> hash = new HashSet<>(); hash.add(5); hash.add(3); hash.add(7); hash.add(1); //迭代器 Iterator<Integer> it = hash.iterator(); while (it.hasNext()){ int num = it.next(); System.out.print(num+" "); } System.out.println("\n=================="); for (int i:hash ) { System.out.println(i); } } }
HashSet集合存储数据的结构(Hash表)
JDK1.8前:Hash底层采用 数组 + 链表 实现
JDK1.8后:Hash底层采用 数组+链表+红黑树 实现(当链表长度超过阈值 8 时,存进红黑树)
特点:hash表查询速度更快
1、存储过程
先计算元素hash值--->分组(hash值相同的元素一组)--->
链表/红黑树结构:把相同hash值的元素连接到一起

2、原理图:

总而言之,JDK1.8引入红黑树大程度的优化了HashMap的性能。
3、关于hash不能存储重复元素(过程)
HashSet存储自定义类型元素
package day03_1; import java.util.Objects; public class Student { //成员属性 private String name; private int age; //无参构造方法 public Student() { } //全参构造方法 public Student(String name, int age) { this.name = name; this.age = age; } //get & set 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; } //重写equals方法 @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Student)) return false; Student student = (Student) o; return getAge() == student.getAge() && Objects.equals(getName(), student.getName()); } //重写hashCode方法 @Override public int hashCode() { return Objects.hash(getName(), getAge()); } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
package day03_1; import java.util.HashSet; public class Main { public static void main(String[] args) { //创建HashSet集合存储学生对象 HashSet<Student> hashSet = new HashSet<>(); Student s1 = new Student("于谦",40); Student s2 =new Student("郭德纲",48); Student s3 = new Student("郭麒麟",26); Student s4 = new Student("郭麒麟",26); //将学生对象 存储到HashSet集合 hashSet.add(s1); hashSet.add(s2); hashSet.add(s3); hashSet.add(s4); //for each 遍历元素 for (Student s:hashSet ) { System.out.println(s); } /** * Student{name='于谦', age=40} * Student{name='郭麒麟', age=26} * Student{name='郭德纲', age=48} */ } }
Set子类--LinkedHashSet集合
我们知道HashSet保证元素唯一性(不重复),但存进去的元素没有顺序,那么如何保证有序存储?
在HashSet下面有一个子类LinkedHashSet,它是链表和哈希表组合的一个数据存储结构
package day03_1; import java.util.Iterator; import java.util.LinkedHashSet; public class Linked_HashSet { public static void main(String[] args) { LinkedHashSet<String> linkedHS = new LinkedHashSet<>(); linkedHS.add("abc"); linkedHS.add("bac"); linkedHS.add("cab"); //迭代遍历元素 Iterator<String> it = linkedHS.iterator(); while (it.hasNext()){ String str = it.next(); System.out.print(str+" ");//abc bac cab } } }
可变参数
在JDK1.5后,定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以将格式简化为:
修饰符 返回值类型 方法名(参数类型...形参名){方法体}
例如:public static Int Sum(int ... numbers){}
之前:public static int Sum(int[] numbers){}
注意:
前面的写法 == 后面的写法
前面的格式的方法能传递数值 而后面的这个方法必须传递数组
package day03_1; public class demo01 { public static void main(String[] args) { //定义数组 int[] arr = {1,3,5,7,9}; //调用方法 int result = getSum(arr); System.out.println(result); } public static int getSum(int[] arr){ int result=0; for (int i:arr ) { result+=i;//此处不能写arr[i] 因为在上面已经定义了一个i来获取元素的值 } return result; } }
package day03_1; public class demo02 { public static void main(String[] args) { int[] arr = {1,3,5,7,9}; //传递数组测试 int Result = getSum(arr); System.out.println(Result);//返回结果 25 //传递普通整型 int value = getSum(1,3,5,7,9); System.out.println(value);//25 } public static int getSum(int...numbers){ int result=0; for (int num:numbers ) { result+=num; } return result; } }
//旧的格式 只能传递数组
//新的格式 能传递数组 也能传递基本元素
Collections(此为工具类)
常用功能
public static <T> boolean addAll(Collection<T> c, T... elements) :往集合中添加一些元素。
格式:Collections.addAll(需要添加元素的集合,元素1,元素2.....)
package day03_1; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; public class Collections_demo { public static void main(String[] args) { //Collection.addAll()方法 Collection<String> coll = new ArrayList<>(); Collections.addAll(coll,"谢霆锋","王菲","何炅"); System.out.println(coll);//[谢霆锋, 王菲, 何炅] } }
public static void shuffle(List<?> list) :打乱集合顺序。
注意:此处创建集合对象不能用Collection<E> 对象名 = new ArrayList<>(); 创建
package day03_1; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; public class Collections_demo { public static void main(String[] args) { //Collection.addAll()方法 ArrayList<String> coll = new ArrayList<>(); Collections.addAll(coll,"谢霆锋","王菲","何炅"); System.out.println(coll);//[谢霆锋, 王菲, 何炅] //Collections.shuffle()方法 Collections.shuffle(coll); System.out.println(coll);//[谢霆锋, 何炅, 王菲] } }
public static <T> void sort(List<T> list) :将集合中元素按照默认规则排序(默认是升序)
注意:重点
sort(List<T> list)使用前提:被排序的集合里面存储的元素,必须实现Comparable,重写接口中的CompareTo方法,定义排序的规则
package day03_1; import java.util.ArrayList; import java.util.Collections; public class Collections_demo02 { public static void main(String[] args) { ArrayList<Integer> arrayList = new ArrayList<>(); arrayList.add(7); arrayList.add(3); arrayList.add(1); arrayList.add(5); System.out.println(arrayList);//[7, 3, 1, 5] Collections.sort(arrayList); System.out.println(arrayList);//[1, 3, 5, 7] } }
Student类继承Comparable接口,并重写Comparable中的CompareTo方法,定义排序规则
package day03_1; import day01.Person; import java.util.Objects; public class Student implements Comparable<Student> { //成员属性 private String name; private int age; //无参构造方法 public Student() { } //全参构造方法 public Student(String name, int age) { this.name = name; this.age = age; } //get & set 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; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } //重写CompareTo方法 定义排序的规则 @Override public int compareTo(Student o) { //return 0;//认为元素都是相同的 //定义比较规则,比较两个人的年龄(this,参数Student) return this.getAge()-o.getAge();//年龄升序 // return o.getAge()-this.getAge() 年龄降序排序 } }
package day03_1; import java.util.ArrayList; import java.util.Collections; public class Collections_demo02 { public static void main(String[] args) { ArrayList<Student> arrayList = new ArrayList<>(); Student s1 = new Student("黎明",18); Student s2 = new Student("刘德华",21); Student s3 = new Student("黄家驹",20); arrayList.add(s1); arrayList.add(s2); arrayList.add(s3); System.out.println(arrayList); //[Student{name='黎明', age=18}, Student{name='刘德华', age=21}, Student{name='黄家驹', age=20}] //Collections.sort(arrayList); 如果没重写CompareTo方法 无法排序 Collections.sort(arrayList); System.out.println(arrayList); //[Student{name='黎明', age=18}, Student{name='黄家驹', age=20}, Student{name='刘德华', age=21}] } }
public static <T> void sort(List<T> list,Comparator<? super T> ) :将集合中元素按照指定规则排序。
Comparable和Comparator两个接口的区别
1、Comparable:
自己(This)和别人(参数)比较,自己需要实现Comparable接口,并重写CompareTo()方法(自定义排序规则)
例如:自己是Student类,
2、Comparator:
相当与找第三方裁判,比较两个
排序规则:
o1-o2升序
package day03_1; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; public class sort_demo { public static void main(String[] args) { ArrayList<Integer> arr = new ArrayList<>(); arr.add(1); arr.add(3); arr.add(2); System.out.println(arr);//[1, 3, 2] //使用Comparato Collections.sort(arr, new Comparator<Integer>() { @Override //重写compare方法 定义排序规则 public int compare(Integer o1, Integer o2) { // return 0; return o1-o2;//升序 } }); System.out.println(arr);//[1, 2, 3] } }
o2-o1降序
package day03_1; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; public class sort_demo { public static void main(String[] args) { ArrayList<Integer> arr = new ArrayList<>(); arr.add(1); arr.add(3); arr.add(2); System.out.println(arr);//[1, 3, 2] //使用Comparato Collections.sort(arr, new Comparator<Integer>() { @Override //重写compare方法 定义排序规则 public int compare(Integer o1, Integer o2) { // return 0; return o2-o1;//降序 } }); System.out.println(arr);//[3, 2, 1] } }
例如:
package day03_1; import day01.Person; import java.util.Objects; public class Student implements Comparable<Student> { //成员属性 private String name; private int age; //无参构造方法 public Student() { } //全参构造方法 public Student(String name, int age) { this.name = name; this.age = age; } //get & set 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; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } //重写CompareTo方法 定义排序的规则 @Override public int compareTo(Student o) { //return 0;//认为元素都是相同的 //定义比较规则,比较两个人的年龄(this,参数Student) return this.getAge()-o.getAge();//年龄升序 // return o.getAge()-this.getAge() 年龄降序排序 } }
package day03_1; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; public class sort_Student { public static void main(String[] args) { ArrayList<Student> arrayList = new ArrayList<>(); arrayList.add( new Student("黎明",18)); arrayList.add( new Student("刘德华",21)); arrayList.add( new Student("黄家驹",20)); System.out.println(arrayList); //[Student{name='黎明', age=18}, Student{name='刘德华', age=21}, Student{name='黄家驹', age=20}] Collections.sort(arrayList, new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { // return 0; //return o1.getAge() - o2.getAge();//升序 return o2.getAge()-o1.getAge();//降序 } }); System.out.println(arrayList); //升序结果:[Student{name='黎明', age=18}, Student{name='黄家驹', age=20}, Student{name='刘德华', age=21}] //降序结果:[Student{name='刘德华', age=21}, Student{name='黄家驹', age=20}, Student{name='黎明', age=18}] } }


浙公网安备 33010602011771号