集合

Java集合详解

可以使用数组来保存多个对象,但数组长度不可变化;为了保存数量不确定的数据,以及保存具有映射关系的数据(也被称为关联数组),Java 提供了集合类。

集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的引用变量),而集合里只能保存对象

Java 集合类型分为 Collection 和 Map,它们是 Java 集合的根接口,这两个接口又包含了一些子接口或实现类。

 

 

 

 

 

Collection接口详解

Collection 接口是 List、Set 和 Queue 接口的父接口,通常情况下不被直接使用。Collection 接口定义了一些通用的方法,通过这些方法可以实现对集合的基本操作。定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。

 

 

  1. public static void main(String[] args) {
  2. ArrayList list1 = new ArrayList(); // 创建集合 list1
  3. ArrayList list2 = new ArrayList(); // 创建集合 list2
  4. list1.add("one"); // 向 list1 添加一个元素
  5. list1.add("two"); // 向 list1 添加一个元素
  6. list2.addAll(list1); // 将 list1 的所有元素添加到 list2
  7. list2.add("three"); // 向 list2 添加一个元素
  8. System.out.println("list2 集合中的元素如下:");
  9. Iterator it1 = list2.iterator();
  10. while (it1.hasNext()) {
  11. System.out.print(it1.next() + "、");
  12. }
  13. }
  1. public static void main(String[] args) {
  2. ArrayList list1 = new ArrayList(); // 创建集合 list1
  3. ArrayList list2 = new ArrayList(); // 创建集合 list2
  4. list1.add("one");
  5. list1.add("two");
  6. list1.add("three");
  7. System.out.println("list1 集合中的元素数量:" + list1.size()); // 输出list1中的元素数量
  8. list2.add("two");
  9. list2.add("four");
  10. list2.add("six");
  11. System.out.println("list2 集合中的元素数量:" + list2.size()); // 输出list2中的元素数量
  12. list2.remove(2); // 删除第 3 个元素
  13. System.out.println("\nremoveAll() 方法之后 list2 集合中的元素数量:" + list2.size());
  14. System.out.println("list2 集合中的元素如下:");
  15. Iterator it1 = list2.iterator();
  16. while (it1.hasNext()) {
  17. System.out.print(it1.next() + "、");
  18. }
  19. list1.removeAll(list2);
  20. System.out.println("\nremoveAll() 方法之后 list1 集合中的元素数量:" + list1.size());
  21. System.out.println("list1 集合中的元素如下:");
  22. Iterator it2 = list1.iterator();
  23. while (it2.hasNext()) {
  24. System.out.print(it2.next() + "、");
  25. }
  26. }

注意:retainAll( ) 方法的作用与 removeAll( ) 方法相反,即保留两个集合中相同的元素,其他全部删除。

 

Java List集合:ArrayList和LinkedList类的用法及区别

List 是一个有序、可重复的集合,集合中每个元素都有其对应的顺序索引。List 集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。List 集合默认按元素的添加顺序设置元素的索引,第一个添加到 List 集合中的元素的索引为 0,第二个为 1,依此类推。

ArrayList 类

ArrayList 类实现了可变数组的大小,存储在内的数据称为元素。它还提供了快速基于索引访问元素的方式,对尾部成员的增加和删除支持较好。使用 ArrayList 创建的集合,允许对集合中的元素进行快速的随机访问,不过,向 ArrayList 中插入与删除元素的速度相对较慢。

ArrayList 类的常用构造方法有如下两种重载形式:

  • ArrayList():构造一个初始容量为 10 的空列表。
  • ArrayList(Collection<?extends E>c):构造一个包含指定 Collection 元素的列表,这些元素是按照该 Collection 的迭代器返回它们的顺序排列的。


ArrayList 类除了包含 Collection 接口中的所有方法之外,还包括 List 接口中提供的如表 1 所示的方法。

 

注意:当调用 List 的 set(int index, Object element) 方法来改变 List 集合指定索引处的元素时,指定的索引必须是 List 集合的有效索引。例如集合长度为 4,就不能指定替换索引为 4 处的元素,也就是说这个方法不会改变 List 集合的长度。

例 1

使用 ArrayList 类向集合中添加三个商品信息,包括商品编号、名称和价格,然后遍历集合输出这些商品信息。

 

  1. public class Product {
  2. // 商品类
  3. private int id; // 商品编号
  4. private String name; // 名称
  5. private float price; // 价格
  6. public Product(int id, String name, float price) {
  7. this.name = name;
  8. this.id = id;
  9. this.price = price;
  10. }
  11. // 这里是上面3个属性的setter/getter方法,这里省略
  12. public String toString() {
  13. return "商品编号:" + id + ",名称:" + name + ",价格:" + price;
  14. }
  15. }
  1. public class Test {
  2. public static void main(String[] args) {
  3. Product pd1 = new Product(4, "木糖醇", 10);
  4. Product pd2 = new Product(5, "洗发水", 12);
  5. Product pd3 = new Product(3, "热水壶", 49);
  6. List list = new ArrayList(); // 创建集合
  7. list.add(pd1);
  8. list.add(pd2);
  9. list.add(pd3);
  10. System.out.println("*************** 商品信息 ***************");
  11. for (int i = 0; i < list.size(); i++) {
  12. // 循环遍历集合,输出集合元素
  13. Product product = (Product) list.get(i);
  14. System.out.println(product);
  15. }
  16. }
  17. }

例 2

 

  1. public static void main(String[] args) {
  2. List list = new ArrayList();
  3. list.add("One");
  4. list.add("|");
  5. list.add("Two");
  6. list.add("|");
  7. list.add("Three");
  8. list.add("|");
  9. list.add("Four");
  10. System.out.println("list 集合中的元素数量:" + list.size());
  11. System.out.println("list 集合中的元素如下:");
  12. Iterator it = list.iterator();
  13. while (it.hasNext()) {
  14. System.out.print(it.next() + "、");
  15. }
  16. System.out.println("\n在 list 集合中'丨'第一次出现的位置是:" + list.indexOf("|"));
  17. System.out.println("在 list 集合中'丨'最后一次出现的位置是:" + list.lastIndexOf("|"));
  18. }

例 3

  1. public static void main(String[] args) {
  2. List list = new ArrayList();
  3. list.add("One");
  4. list.add("Two");
  5. list.add("Three");
  6. list.add("Four");
  7. list.add("Five");
  8. list.add("Six");
  9. list.add("Seven");
  10. System.out.println("list 集合中的元素数量:" + list.size());
  11. System.out.println("list 集合中的元素如下:");
  12. Iterator it = list.iterator();
  13. while (it.hasNext()) {
  14. System.out.print(it.next() + "、");
  15. }
  16. List sublist = new ArrayList();
  17. sublist = list.subList(2, 5); // 从list集合中截取索引2~5的元素,保存到sublist集合中
  18. System.out.println("\nsublist 集合中元素数量:" + sublist.size());
  19. System.out.println("sublist 集合中的元素如下:");
  20. it = sublist.iterator();
  21. while (it.hasNext()) {
  22. System.out.print(it.next() + "、");
  23. }
  24. }

LinkedList类

LinkedList 类采用链表结构保存对象,这种结构的优点是便于向集合中插入或者删除元素。需要频繁向集合中插入和删除元素时,使用 LinkedList 类比 ArrayList 类效果高,但是 LinkedList 类随机访问元素的速度则相对较慢。这里的随机访问是指检索集合中特定索引位置的元素。

LinkedList 类除了包含 Collection 接口和 List 接口中的所有方法之外,还特别提供了表 2 所示的方法。

 

例 4

 

  1. public class Test {
  2. public static void main(String[] args) {
  3. LinkedList<String> products = new LinkedList<String>(); // 创建集合对象
  4. String p1 = new String("六角螺母");
  5. String p2 = new String("10A 电缆线");
  6. String p3 = new String("5M 卷尺");
  7. String p4 = new String("4CM 原木方板");
  8. products.add(p1); // 将 p1 对象添加到 LinkedList 集合中
  9. products.add(p2); // 将 p2 对象添加到 LinkedList 集合中
  10. products.add(p3); // 将 p3 对象添加到 LinkedList 集合中
  11. products.add(p4); // 将 p4 对象添加到 LinkedList 集合中
  12. String p5 = new String("标准文件夹小柜");
  13. products.addLast(p5); // 向集合的末尾添加p5对象
  14. System.out.print("*************** 商品信息 ***************");
  15. System.out.println("\n目前商品有:");
  16. for (int i = 0; i < products.size(); i++) {
  17. System.out.print(products.get(i) + "\t");
  18. }
  19. System.out.println("\n第一个商品的名称为:" + products.getFirst());
  20. System.out.println("最后一个商品的名称为:" + products.getLast());
  21. products.removeLast(); // 删除最后一个元素
  22. System.out.println("删除最后的元素,目前商品有:");
  23. for (int i = 0; i < products.size(); i++) {
  24. System.out.print(products.get(i) + "\t");
  25. }
  26. }
  27. }

 

 

ArrayList 类和 LinkedList 类的区别

ArrayList 是基于动态数组数据结构的实现,访问元素速度优于 LinkedList。LinkedList 是基于链表数据结构的实现,占用的内存空间比较大,但在批量插入或删除数据时优于 ArrayList。

 Set集合:HashSet和TreeSet类

Set 集合中不能包含重复的对象,并且最多只允许包含一个 null 元素。

HashSet 类

HashSet 是按照 Hash 算法来存储集合中的元素。因此具有很好的存取和查找性能。

HashSet 具有以下特点:

  • 不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。
  • HashSet 不是同步的,如果多个线程同时访问或修改一个 HashSet,则必须通过代码来保证其同步。
  • 集合元素值可以是 null。

当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据该 hashCode 值决定该对象在 HashSet 中的存储位置。如果有两个元素通过 equals() 方法比较返回的结果为 true,但它们的 hashCode 不相等,HashSet 将会把它们存储在不同的位置,依然可以添加成功。

也就是说,两个对象的 hashCode 值相等且通过 equals() 方法比较返回结果为 true,则 HashSet 集合认为两个元素相等。

 

  1. HashSet hs = new HashSet(); // 调用无参的构造函数创建HashSet对象
  2. HashSet<String> hss = new HashSet<String>(); // 创建泛型的 HashSet 集合对象
  1. public static void main(String[] args) {
  2. HashSet<String> courseSet = new HashSet<String>(); // 创建一个空的 Set 集合
  3. String course1 = new String("Java入门教程");
  4. String course2 = new String("Python基础教程");
  5. String course3 = new String("C语言学习教程");
  6. String course4 = new String("Golang入门教程");
  7. courseSet.add(course1); // 将 course1 存储到 Set 集合中
  8. courseSet.add(course2); // 将 course2 存储到 Set 集合中
  9. courseSet.add(course3); // 将 course3 存储到 Set 集合中
  10. courseSet.add(course4); // 将 course4 存储到 Set 集合中
  11. System.out.println("C语言中文网教程有:");
  12. Iterator<String> it = courseSet.iterator();
  13. while (it.hasNext()) {
  14. System.out.println("《" + (String) it.next() + "》"); // 输出 Set 集合中的元素
  15. }
  16. System.out.println("有" + courseSet.size() + "套精彩教程!");
  17. }

TreeSet 类

TreeSet 类同时实现了 Set 接口和 SortedSet 接口。SortedSet 接口是 Set 接口的子接口,可以实现对集合进行自然排序,这里的自然排序指的是升序排序。

TreeSet 只能对实现了 Comparable 接口的类对象进行排序,因为 Comparable 接口中有一个 compareTo(Object o) 方法用于比较两个对象的大小。

如果 a 和 b 相等,则该方法返回 0;如果 a 大于 b,则该方法返回大于 0 的值;如果 a 小于 b,则该方法返回小于 0 的值。

 

 

 

  1. public class Test08 {
  2. public static void main(String[] args) {
  3. TreeSet<Double> scores = new TreeSet<Double>(); // 创建 TreeSet 集合
  4. Scanner input = new Scanner(System.in);
  5. System.out.println("------------学生成绩管理系统-------------");
  6. for (int i = 0; i < 5; i++) {
  7. System.out.println("第" + (i + 1) + "个学生成绩:");
  8. double score = input.nextDouble();
  9. // 将学生成绩转换为Double类型,添加到TreeSet集合中
  10. scores.add(Double.valueOf(score));
  11. }
  12. Iterator<Double> it = scores.iterator(); // 创建 Iterator 对象
  13. System.out.println("学生成绩从低到高的排序为:");
  14. while (it.hasNext()) {
  15. System.out.print(it.next() + "\t");
  16. }
  17. System.out.println("\n请输入要查询的成绩:");
  18. double searchScore = input.nextDouble();
  19. if (scores.contains(searchScore)) {
  20. System.out.println("成绩为: " + searchScore + " 的学生存在!");
  21. } else {
  22. System.out.println("成绩为: " + searchScore + " 的学生不存在!");
  23. }
  24. // 查询不及格的学生成绩
  25. SortedSet<Double> score1 = scores.headSet(60.0);
  26. System.out.println("\n不及格的成绩有:");
  27. for (int i = 0; i < score1.toArray().length; i++) {
  28. System.out.print(score1.toArray()[i] + "\t");
  29. }
  30. // 查询90分以上的学生成绩
  31. SortedSet<Double> score2 = scores.tailSet(90.0);
  32. System.out.println("\n90 分以上的成绩有:");
  33. for (int i = 0; i < score2.toArray().length; i++) {
  34. System.out.print(score2.toArray()[i] + "\t");
  35. }
  36. }
  37. }

注意:在使用自然排序时只能向 TreeSet 集合中添加相同数据类型的对象,否则会抛出 ClassCastException 异常

 

Map集合详解

Map 是一种键-值对(key-value)集合,Map 集合中的每一个元素都包含一个键(key)对象和一个值(value)对象。用于保存具有映射关系的数据。

Map 的 key 不允许重复,value 可以重复

Map 接口主要有两个实现类:HashMap 类和 TreeMap 类。其中,HashMap 类按哈希算法来存取键对象,而 TreeMap 类可以对键对象进行排序。

 

 

  1. public class Test09 {
  2. public static void main(String[] args) {
  3. HashMap users = new HashMap();
  4. users.put("11", "张浩太"); // 将学生信息键值对存储到Map中
  5. users.put("22", "刘思诚");
  6. users.put("33", "王强文");
  7. users.put("44", "李国量");
  8. users.put("55", "王路路");
  9. System.out.println("******** 学生列表 ********");
  10. Iterator it = users.keySet().iterator();
  11. while (it.hasNext()) {
  12. // 遍历 Map
  13. Object key = it.next();
  14. Object val = users.get(key);
  15. System.out.println("学号:" + key + ",姓名:" + val);
  16. }
  17. Scanner input = new Scanner(System.in);
  18. System.out.println("请输入要删除的学号:");
  19. int num = input.nextInt();
  20. if (users.containsKey(String.valueOf(num))) { // 判断是否包含指定键
  21. users.remove(String.valueOf(num)); // 如果包含就删除
  22. } else {
  23. System.out.println("该学生不存在!");
  24. }
  25. System.out.println("******** 学生列表 ********");
  26. it = users.keySet().iterator();
  27. while (it.hasNext()) {
  28. Object key = it.next();
  29. Object val = users.get(key);
  30. System.out.println("学号:" + key + ",姓名:" + val);
  31. }
  32. }

 

posted @ 2020-03-12 08:53  不良小帅  阅读(191)  评论(0编辑  收藏  举报