一、什么是集合?
在Java中,集合(Collection)指的是一组数据容器,它可以存储多个对象,并且允许用户通过一些方法来访问与操作这些对象。Java提供了一系列接口和类来支持不同类型的集合。 Collection接口,主要用于存放单一元素; Map 接口,主要用于存放键值对。
二、Java集合和数组的区别?
数组不是面向对象的,存在明显的缺陷,集合弥补了数组的缺点,比数组更灵活更实用,而且不同的集合框架类可适用不同场合。
- 数组存放基本数据类型和对象,而集合类存放的都是对象,集合类不能存放基本数据类型。数组和集合存放的对象皆为对象的引用地址;
- 数组容易固定无法动态改变,集合类容量动态改变;
- 数组无法判断其中实际存有多少元素,length只告诉了数组的容量,而集合的size()可以确切知道元素的个数;
- 集合有多种实现方式和不同适用场合,数组仅采用顺序表方式
- 集合以类的形式存在,具有封装、继承、多态等类的特性,通过简单的方法和属性即可实现各种复杂操作,大大提高了软件的开发效率。
三、Java集合框架

四、List
继承自Collection,是一个有序的集合,可以包含重复元素。
实现类:
- ArrayList:数组实现,查询快,增删慢,轻量级;(线程不安全)
- LinkedList:双向链表实现,增删快,查询慢 (线程不安全)
- Vector:数组实现,重量级 (线程安全、使用少)
ArrayList和LinkedList区别
ArrayList是基于动态数组实现的,而LinkedList是基于双向链表实现的。它们都实现了List接口。
| ArrayList | LinkedList | |
| 获取指定元素 | 速度很快 | 需要从头开始查找元素 |
| 添加元素到末尾 | 速度很快 | 速度很快 |
| 在指定位置添加/删除 | 需要移动元素 | 不需要移动元素 |
| 内存占用 | 少 | 较大 |
ArrayList适合随机访问,而LinkedList适合插入和删除操作。在选择列表实现时,需要根据实际的用例来决定。如果应用场景中包含大量的插入和删除操作,LinkedList可能是更好的选择。相反,如果需要频繁地随机访问元素,ArrayList将提供更好的性能。
List特点
List接口允许我们添加重复的元素,即List内部的元素可以重复:
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("apple"); // size=1
list.add("pear"); // size=2
list.add("apple"); // 允许重复添加元素,size=3
System.out.println(list.size());
}
List还允许添加null:
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("apple"); // size=1
list.add(null); // size=2
list.add("pear"); // size=3
String second = list.get(1); // null
System.out.println(second);
}
List遍历方法
// 索引
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
for (int i=0; i<list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
}
//迭代器Iterator
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
String s = it.next();
System.out.println(s);
}
}
//foreach
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
for (String s : list) {
System.out.println(s);
}
}
List转Array
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
Object[] array = list.toArray();
for (Object s : array) {
System.out.println(s);
}
}
public static void main(String[] args) {
List<Integer> list = List.of(12, 34, 56);
Integer[] array = list.toArray(new Integer[3]);
for (Integer n : array) {
System.out.println(n);
}
}
Array转List
Integer[] array = { 1, 2, 3 };
List<Integer> list = List.of(array);
五、Set
继承自Collection,是一个无序集合,不允许存放重复的元素;允许使用null元素。
HashSet
- 基于哈希表实现,不保证元素的顺序,不是线程安全的,存取速度比较快,不允许保存重复元素(可以实现去重操作);
-
底层是HashMap,放到HashSet集合中的元素等同于放到HashMap集合key部分了;
-
HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取、查找、删除性能
HashSet添加元素过程
- 首先判断hashCode()值是否相同
- ->继续执行equals(),看其返回值
- ->是true:说明元素重复,不添加 是false:就直接添加到集合
- ->否:就直接添加到集合
- 最终自动生成hashCode()和equals()
LinkedHashSet
也是基于哈希表,但它维护了一个链表来保证插入顺序。
TreeSet
- 有序,唯一,不重复 ,不允许为null主要用作排序,自然排序和定制排序,默认情况下,TreeSet 采用自然排序;
-
底层是TreeMap,放到TreeSet集合中的元素等同于放到TreeMap集合key部分了,红黑树(自平衡的排序二叉树);
-
TreeSet的有序存储,存储元素时会判断他是否重复,并且自动排序,判断重复元素由compareTo()方法来实现。因此自定义类要使用TreeSet必须覆写Comparable接口。具体的排序规则可以由我们自己来定
┌───┐
│Set│
└───┘
▲
┌────┴─────┐
│ │
┌───────┐ ┌─────────┐
│HashSet│ │SortedSet│
└───────┘ └─────────┘
▲
│
┌─────────┐
│ TreeSet │
└─────────┘
// HashSet
Set<String> hashSet = new HashSet<>();
hashSet.add("Java");
hashSet.add("Kotlin");
// LinkedHashSet
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("Java");
linkedHashSet.add("Kotlin");
// TreeSet
Set<String> treeSet = new TreeSet<>();
treeSet.add("Java");
treeSet.add("Kotlin");
六、Map
提供了一组键值对的映射。其中存储的每个对象都有一个相应的关键字(key),关键字决定了对象在Map中的存储位置。关键字应该是唯一的,每个key 只能映射一个value。
| 实现类 | 数据结构 | 是否线程安全 | key能否为null | 是否有序 |
|---|---|---|---|---|
| HashMap | 数组+链表+红黑树 | 否 | 是 | 否 |
| LinkedHashMap | 数组+链表+红黑树+双重链接列表 | 否 | 是 | 是 |
| Hashtable | 数组+链表 | 是 | 否 | 否 |
| TreeMap | 红黑树 | 否 | 否 | 是 |
HashMap
HashMap是 Map 接口使用频率最高的实现类。
- 允许使用null键和null值,与HashSet一样,不保证映射的顺序。
- 所有的key构成的集合是Set:无序的、不可重复的。所以,key所在的类要重写:equals()和hashCode()
- 所有的value构成的集合是Collection:无序的、可以重复的。所以,value所在的类要重写:equals()
一个key-value构成一个entry - 所有的entry构成的集合是Set:无序的、不可重复的
HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。
注:
JDK 7及以前版本:HashMap是数组+链表结构(即为链地址法)
JDK 8版本发布以后:HashMap是数组+链表+红黑树实现。
LinkedHashMap
LinkedHashMap继承了HashMap,是Map接口的哈希表和链接列表实现,它维护着一个双重链接列表,此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。
Hashtable
- Hashtable是早期的字典实现类,可以方便的实现数据的查询
- Hashtable和HashMap从存储结构和实现来讲有很多相似之处,不同的是它承自Dictionary类,而且是线程安全的,另外Hashtable不允许key和value为null,并发性不如ConcurrentHashMap。
- Hashtable不建议在新代码中使用,不需要线程安全的场合可以用HashMap替换,需要线程安全的场合可以用ConcurrentHashMap替换。
Properties
- Properties 类是 Hashtable 的子类,该对象用于处理属性文件
- 由于属性文件里的 key、value 都是字符串类型,所以 Properties 里的 key 和 value 都是字符串类型
- 存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法
TreeMap
Map集合的主要功能是依据key实现数据的查询需求,为了方便进行key排序操作提供了TreeMap集合,TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序(自然顺序),也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。
List、Set和Map各自适用于不同的场景,例如,当需要保持元素顺序时使用List,当需要唯一性时使用Set,而当需要存储键值对时使用Map。

322

被折叠的 条评论
为什么被折叠?



