集合在Java中的使用和比较
在Java编程中,集合框架是一个非常重要的组成部分,它提供了一种存储和操作数据的方式。集合框架包括多种类型的集合,每种集合都有其特定的用途和特点。本文将对Java中的几种常见集合进行介绍和比较,帮助读者更好地理解和使用它们。
List接口的实现类
ArrayList
ArrayList
是基于动态数组实现的,它允许对元素进行快速随机访问。然而,当需要在中间位置添加或删除元素时,效率较低,因为需要移动数组中的其他元素以维持数组的连续性。
特点:
- 线程不安全
- 查询效率高
- 添加删除中间元素效率低
示例代码:
ArrayList<Object> arrayList = new ArrayList<>();
arrayList.add(13);
arrayList.add("张三1");
arrayList.add(true);
arrayList.add("张三2");
// 数据插入:在指定位置添加对象
arrayList.add(2, "张三2");
// 获取数组长度
System.out.println("集合长度: " + arrayList.size());
// 获取指定位置的元素
System.out.println("第一个元素: " + arrayList.get(0));
// 移除集合中指定元素
arrayList.remove(2); // 删除索引为2的元素
arrayList.remove("张三1"); // 删除集合中第一个出现的对象
// 修改集合元素对象的值
arrayList.set(0, "李四");
// 循环输出集合元素对象
for (int i = 0; i < arrayList.size(); i++) {
System.out.print(" " + arrayList.get(i));
}
// 集合清空
arrayList.clear();
// 判断是否为空
System.out.println("是否为空: " + arrayList.isEmpty());
LinkedList
LinkedList
是基于双向链表实现的,它允许在列表的开始或结束位置快速添加和删除元素。但是,访问特定位置的元素时,需要从头或尾开始遍历,因此查询效率较低。
特点:
- 双向链表
- 添加元素效率高
- 查询效率低
示例代码:
LinkedList<String> list1 = new LinkedList<>();
list1.add("张三1");
list1.add("张三2");
list1.add("李四");
// 修改
list1.set(1, "王五");
// 删除
list1.remove(1); // 删除索引为1的元素
// 根据索引查找元素
System.out.println(list1.get(0));
// 遍历
for (String item : list1) {
System.out.println(item);
}
Vector
Vector
与ArrayList
类似,但它是线程安全的。由于其线程安全性,Vector
的性能通常不如ArrayList
,因此除非需要线程安全,否则推荐使用ArrayList
。
示例代码:
Vector<Integer> vector = new Vector<>();
vector.add(10);
vector.add(20);
int firstElement = vector.get(0); // 获取第一个元素
for (Integer i : vector) {
System.out.println(i);
}
// 线程安全的Vector
vector = Collections.synchronizedList(new Vector<>());
Set接口的实现类
HashSet
HashSet
是基于哈希表实现的,它使用数组、链表和红黑二叉树来存储元素。HashSet
不允许存储重复的元素,并且元素的存储和访问是无序的。
特点:
- 无序
- 不重复
- 无索引
示例代码:
// 1.新建对象
HashSet hashSet = new HashSet();
// 2.添加元素
hashSet.add("Hello");
hashSet.add("World");
hashSet.add("java");
// 3.遍历Set集合中元素对象
System.out.println("打印输出"+hashSet); //运行结果:[java, Hello, World]
// 3.1 增强for循环
System.out.println("使用增强for循环遍历Set集合中元素对象");
for(Object o:hashSet){
System.out.println(o);
}
/* 3.2 普通for循环 不能实现
for (int i = 0; i < hashSet.size(); i++) {
System.out.println();
}*/
// 3.3 使用迭代器
System.out.println("使用迭代器遍历Set集合中元素对象");
Iterator iterator = hashSet.iterator();
while (iterator.hasNext()) {//判断是否有下一个元素
Object next = iterator.next();
System.out.println(next);
}
// 4.集合长度
System.out.println("集合长度"+hashSet.size());
TreeSet
TreeSet
使用红黑树结构对元素进行排序,因此它能够提供自然排序的元素。与HashSet
相比,TreeSet
在添加元素时效率较低,但在查找元素时效率稍高。
特点:
- 实现自然排序
- 查找效率稍高
- 添加元素效率低
示例代码:
TreeSet<String> set = new TreeSet<>();
set.add("apple");
set.add("banana");
set.add("cherry");
// TreeSet自然排序
System.out.println("TreeSet: " + set);
LinkedHashSet
LinkedHashSet
结合了HashSet
和LinkedHashMap
的特点,它使用哈希表和链表来存储元素,保证了元素的有序性。
特点:
- 元素有序
- 无重复
示例代码:
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("hello");
set.add("world");
set.add("zhangsan");
set.add("ls");
set.add("zhangsan"); // 不会重复添加
System.out.println("LinkedHashSet: " + set);
Map接口的实现类
LinkedHashMap
LinkedHashMap
类似于HashMap
,但它维护了一个双向链表,使得元素的插入顺序或者访问顺序可以被跟踪。
特点:
- 双链表结构+哈希表结构
- 添加效率高于HashMap
示例代码:
LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
// 遍历LinkedHashMap
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
Hashtable
Hashtable
是一个古老的集合类,它是线程安全的。它不允许空键和空值,并且所有的操作都是同步的。
示例代码:
Hashtable hashtable = new Hashtable();
//添加值
hashtable.put("CN","中国");
hashtable.put("USA","美国");
hashtable.put("JP","日本");
//3.元素个数
System.out.println(hashtable.size());
//清空集合
//hashtable.clear();
//替换
hashtable.replace("USA","欧美");
//遍历1
Collection<String> values = hashtable.values();
for(String value:values){
System.out.println(value);
}
System.out.println("----------------");
//
Set<String> set = hashtable.keySet();
for(String key:set){
System.out.println(hashtable.get(key));
}
System.out.println("----------------");
Set<Map.Entry<String,String>> entrys = hashtable.entrySet();
for (Map.Entry<String,String> entry:entrys){
System.out.println("Key:"+entry.getKey()+",Value:"+entry.getValue());
}
System.out.println("----------------");
//遍历4
hashtable.forEach((key,value) ->{
System.out.println("Key:"+key+" value"+value);
});
System.out.println("---------------");
Enumeration<String> elements = hashtable.elements();
//迭代枚举接口
while (elements.hasMoreElements()){
System.out.println(elements.nextElement());
}
ConcurrentHashMap
ConcurrentHashMap
提供了完全并发性的检索和高预期并发性的更新操作。它是线程安全的,并且性能优于Hashtable
。
特点:
- 支持完全并发性检索
- 更新操作具有高预期并发性
示例代码:
ConcurrentHashMap<Integer,Integer> concurrentHashMap = new ConcurrentHashMap();
concurrentHashMap.put(1,3);
concurrentHashMap.put(2,8);
concurrentHashMap.put(6,3);
concurrentHashMap.put(5,6);concurrentHashMap.put(1,3);
long before=System.currentTimeMillis();
/* forEach:对每个元素执行给定的操作。 变量形式在执行操作之前对每个元素应用给定的变换。*/
//forEach遍历
concurrentHashMap.forEach(5,(key1,value)->{
System.out.println("Key:"+key1+" value:"+value);
});
//search search:返回在每个元素上应用给定函数的第一个可用非空结果; 当找到结果时跳过进一步的搜索。
String result=concurrentHashMap.search(5,(key,value)->{
if(key == 5){
return "存在5的key值";
}
else{
return null;
}
});
System.out.println(result);
// reduce:累积每个元素。 提供的减少功能不能依赖于排序(更正式地,它应该是关联和交换)。
Integer val=concurrentHashMap.reduce(5,(key1,value)->{
return key1;
},(o1,o2)->{
return o1-o2;
});
System.out.println(val);
concurrentHashMap.forEachEntry(5,(entry)->{
System.out.println("key:"+entry.getKey()+" 值: "+entry.getValue());
});
总结
Java集合框架提供了多种类型的集合,每种集合都有其特定的用途和特点。选择合适的集合类型对于提高程序的性能和可读性至关重要。希望本文能够帮助读者更好地理解Java中的集合,并在实际编程中做出恰当的选择。