1.集合、数组、容器分别是什么?
-
数组 (Array):
-
数组是一种固定大小的数据结构,它可以容纳一组相同类型的元素。
-
数组的大小在创建时确定,不可改变。
-
数组可以直接通过索引访问元素,访问速度很快。
-
数组可以存储基本数据类型(如 int、char、float)或对象引用。
-
数组的元素在内存中是连续存储的。
-
示例:
int[] numbers = new int[5];
-
-
集合 (Collection):
-
集合是一种动态大小的数据结构,可以容纳一组元素。
-
集合的大小可以根据需要动态增加或减少,不需要手动指定大小。
-
集合通常用于存储对象(类的实例),而不是基本数据类型。
-
集合提供了丰富的操作方法,如添加、删除、查询、遍历等。
-
集合框架包括 List、Set、Map 等不同类型的集合。
-
示例:
List<String> names = new ArrayList<>();
-
-
容器 (Container):
-
容器是一个更加通用的术语,它包括了数组和集合在内。
-
容器用于存储和组织数据,可以根据需要选择合适的数据结构。
-
容器的目的是管理数据的存储和访问,提供数据操作的方法。
-
容器可以是数组,也可以是集合,取决于具体的需求和场景。
-
容器的概念更广泛,不局限于特定的数据结构或类型。
-
总结来说,数组是一种静态大小的数据结构,集合是一种动态大小的数据结构,而容器是一个更通用的术语,可以包括数组和集合在内,用于数据的存储和组织。在 Java 中,集合框架提供了丰富的集合类,用于处理各种数据结构和操作需求。
2.数组
在 Java 中,有多种类型的数组,包括以下几种主要类型:
-
一维数组(One-Dimensional Arrays): 一维数组是最简单的数组类型,用于存储一组相同类型的数据。
.java int[] numbers = {1, 2, 3, 4, 5}; // 整数数组 String[] names = {"Alice", "Bob", "Charlie"}; // 字符串数组
-
二维数组(Two-Dimensional Arrays): 二维数组是一种表格结构,可以看作是数组的数组。 它用于存储具有行和列的数据。
.java int[][] matrix = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
-
多维数组(Multi-Dimensional Arrays): 多维数组可以有更多维度,例如三维数组、四维数组等。 这些数组嵌套包含多个数组。
.java int[][][] threeDArray = new int[3][4][2]; // 三维数组
-
动态数组(Dynamic Arrays): 动态数组是通过 ArrayList 类实现的,它可以根据需要自动增长或缩小大小,不需要指定固定长度。
.java import java.util.ArrayList; List<Integer> dynamicArray = new ArrayList<>(); dynamicArray.add(1); dynamicArray.add(2);
引用数据类型的数组
String[] stringArray = new String[3]; // 创建一个字符串数组 // 分别为数组中的元素赋值 stringArray[0] = "Hello"; stringArray[1] = "World"; stringArray[2] = "Java"; // 访问数组中的元素 System.out.println(stringArray[0]); // 输出 "Hello" System.out.println(stringArray[1]); // 输出 "World" System.out.println(stringArray[2]); // 输出 "Java"
自定义类对象数组: 您可以创建自定义类的对象数组。 例如,如果有一个 Person
类:
.java Person[] peopleArray = new Person[3]; // 创建一个 Person 类型的数组
集合类对象数组: 您可以创建存储集合对象的数组,例如 ArrayList
:
.java ArrayList<Integer>[] arrayOfLists = new ArrayList[5]; // 创建一个 ArrayList 数组
接口实现类对象数组: 如果有一个接口并有多个实现类,您可以创建存储接口对象的数组。 例如,如果有一个 Shape
接口和实现它的 Circle
和 Rectangle
类:
.java Shape[] shapesArray = new Shape[2]; // 创建一个存储 Shape 接口对象的数组 shapesArray[0] = new Circle(); shapesArray[1] = new Rectangle();
枚举类型数组: 您可以创建存储枚举类型的数组:
.java enum Days { MONDAY, TUESDAY, WEDNESDAY } Days[] daysArray = new Days[3]; // 创建一个枚举类型数组
其他类的对象数组: 任何自定义类的对象都可以存储在数组中,这取决于您的应用程序需要。
这些是 Java 中常见的数组类型。 你可以根据实际需求选择适当的数组类型来存储和处理数据。
理解
总的来说万物皆可数组,可以创建包含几乎任何类型的对象的数组,因此数组是非常灵活的数据结构。 这使得它成为在Java中处理各种数据和对象的重要工具之一。 无论是基本数据类型还是引用数据类型,都可以用数组来组织和管理。 这种灵活性使得数组在编写各种类型的应用程序时都非常有用。
3.集合
集合存放于until包中,我们可以理解为顶级父类有Collection、Map两个父类,其中Collection的子类有List、Set,Map的子类则是HashMap、TreeMap。
不同集合的特点
(1)List 特点:有序、可重复 (2)Set 特点:无序、不可重复 (3)Collection 特点:无序、可重复 (4)Map 特点:无序,不可重复,存放【键值对】(key 键 -- value 值)
List常用方法
(1)add(o)方法,在末尾添加一个对象 (2)add(int index,o),在指定索引位插入一个对象 (3)set(int index,o),将指定索引位 (4)get(int index),返回指定索引位的对象 (5)remove(int index),删除指定索引位的对象并返回它 (6)remove(o),删除第一个指定的对象,返回值为布尔类型,表示是否删除成功 (7)contains(o),判断是否存在指定的对象,返回值为布尔类型 (8)size(),返回List包含的元素个数(int类型) (9)indexOf(o),返回该元素的第一个索引值,没有返回-1 (10)clear(),清空List 而LinkedLisk则多了头部添加、头部删除、尾部添加、尾部删除
addFirst(o),addLast(o),removeFirst(),removeLast()
Set常用方法与List相差不大
但是值得注意的是其子类TreeSet、HashSet的特殊性
TreeSet
TreeSet
是 Java 中的一个类,它实现了 Set
接口,并使用红黑树作为其底层数据结构。它会维护元素的排序顺序。
红黑树
红黑树是一种自平衡的二叉搜索树,它的设计和算法确保了树的高度相对较小,从而保持了树的平衡。 这个平衡性质使得红黑树在执行插入、删除、查找等基本操作时能够保持较低的时间复杂度,通常为 O(log n),其中 n 是树中节点的数量。
通过维护颜色规则和黑高度规则,红黑树可以自我平衡,确保树的结构不会偏向某一侧,从而避免了树的高度过高,保持了高效的操作性能。 因此,红黑树在实际应用中非常有价值,用于构建有序集合、映射等数据结构,以及需要高效查找和维护平衡性的场景。
也就是说红黑树其实是一种算法可以保持树的高度维持在一个较小的高度从而达到树的平衡进行增删改查
总的来说TreeSet是一个有序的、不可重复的集合。而HashSet则是一个无序的、不可重复的集合
Map
Hash是什么?
哈希(Hash)是一种算法,用于将任意大小的数据映射为固定大小的哈希码(通常是一个整数)。这个算法将数据压缩成一个固定长度的唯一标识,这个标识可以用作数据的索引或用于数据的快速比较。哈希算法在许多领域都有广泛的应用,包括数据存储、加密、数据校验等。
当哈希算法与数据结构结合使用时,通常是为了实现高效的数据存储和检索。例如,哈希表(Hash Table)是一种常见的数据结构,它使用哈希算法将键映射到存储桶中,并且能够快速地通过键来查找对应的值,这大大提高了数据的检索速度。
也就是说hash是一种算法,当他与我们的数据结构结合的时候算法就是对数据最小单位存储方式的体现
HashMap、HashSet这样子结合后又说明什么?
首先Map、Set是一种数据结构,前者以键值对的形式存放数据、后者则是一个无序不可重复的集合
他们与hash结合后=存放的每一个数据都会被hash算法转换成哈希码存放在存储桶中方便进行快速查找
而存储桶与HashMao/HashSet的关系是:Hash码存放在存储桶中,而这个桶存放在内存当中,但是它属于HashMap的一部分,而桶的本质其实也是一个数组,这个素组的数据结构是一个链表某种情况下会变成红黑树进行存储
也就是说任何带hash字样的数据结构都表示他的内部数据会以哈希码的形式存储在存储桶中方便快速查找
HashMap的常用方法
(1)put(key,value),添加一个键值对,返回null,key和value都是Object,如果已经存在key,则更改value为新的值并将其返回 (2)get(key),返回key对应的value,如果没有,返回null (3)remove(key),删除相应的键值对,返回删除掉的value,如果没有返回null (4)containsKey(key),containsValue(value),返回值为boolean类型 (5)size(),返回包含的键值对数量 (6)keySet(),返回包含所有key值的Set集合 (7)values(),返回包含所有value值的Collection集合 Tree也同理
遍历
Iterator接口
每个Collection类的对象都要实现Iterator接口下约定的iterator()方法,这个方法实际上是返回一个集合的迭代器,用于遍历集合,Iterator主要带有两个方法hasNext()和next()方法。
两个方法的说明
hasNext()方法是判断集合中是否存在下一个元素,返回值为布尔值类型 next()方法是返回下一个元素的值 一般采用while循环的方式,当hasNext()为true时,将下一个元素的值返回出来,如果为false则退出循环。
foreach循环遍历
foreach实际上底层也是使用Iterator接口实现的,两者在遍历原理上只有细微的差别。
List list = new ArrayList(); list.add("1234"); list.add(-1); list.add("abcd"); for (Object i: list) { System.out.println(i.toString()); } /* 结果为 1234 -1 abcd */ Map集合 Map map = new HashMap(); map.put("姓名","张三"); map.put("年龄","22"); for (Object i :map.keySet()) { String key = i.toString(); System.out.print("key="+key); System.out.println("value="+map.get(key)); } //结果与使用Iterator接口的遍历是一样的
普通for循环
普通for循环只能对有序的集合进行遍历,也就是ArrayList和LinkedList,下面以LinkedList为例,方法与普通数组一样,只不过需要将length属性改为size()方法
List list = new LinkedList(); list.add("gggg"); list.add("haha"); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } /* 结果为 gggg haha */
泛型
集合中使用泛型规定了集合中每个元素的类型为规定好的同一类型,使用方法为<数据类型>,我们在平常使用集合时,尽管可以不使用泛型限定添加的类型,但太过随意的添加任意类型的值会导致集合可能产生数据类型的污染,并且在使用一些方法时可能会有数据类型参数的不匹配而导致异常,因此在使用集合时,必须要加上泛型对其中元素的类型进行限定。
使用泛型
List<String> list1 = new ArrayList<String>();//前后都要使用泛型标识符 List<String> list2 = new LinkedList<>();//后面<>内的内容可以省略