java中的集合框架
java集合框架概述
集合框架可以看做是一种容器,用来储存对像信息。所有集合类都位于java.util包下,但支持多线程的集合类位于java.util.concurrent包下。
集合框架被设计成满足一下几个目标:
- 该框架必须是高性能的。基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的
- 该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。
- 对一个集合的扩展和适应必须是简单的。
为此,整个集合框架就围绕一组标准接口而设计。你可以直接使用这些接口的标准实现,诸如: LinkedList, HashSet, 和 TreeSet 等,除此之外你也可以通过这些接口实现自己的集合。
集合框架是一个用来代表和操纵集合的统一 架构。所有的集合框架都包含如下内容:
-
接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象
-
实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。
-
算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。
数组与集合的区别
- 数组长度不可变化而且无法保存具有映射关系的数据;集合类用于保存数量不确定的数据,以及保存具有映射关系的数据。
- 数组元素既可以是基本类型的值,也可以是对象;集合只能保存对象。
java的基本数据类型进行了一个封装 封装到了一个类中
基本数据 | 封装的类 |
---|---|
boolean | Boolean |
char | Character |
byte | Byte |
short | Short |
long | Long |
int | Integer |
float | Float |
double | Double |
java集合常见接口和实现类
Collection接口常见方法(java api)
Set集合
Set集合与Collection的方法相同,由于Set集合不允许存储相同的元素,所以如果把两个相同元素添加到同一个Set集合,则添加操作失败,新元素不会被加入,add()方法返回false。
package csdnTest;
import java.util.HashSet;
import java.util.Set;
public class ListTest {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("a");
set.add("b");
set.add("b");//添加不进去
System.out.println("集合中元素个数:"+set.size());
System.out.println("集合中元素为:"+set.toString());
}
}
结果为
集合中元素个数:2
集合中元素为:[a, b]
HashSet
HashSet是Set集合最常用实现类,是其经典实现。HashSet是按照哈希表算法来存储元素的,因此具有很好的存取和查找性能。
HashSet具有如下特点:
- HashSet 是无序的,即不会记录插入的顺序。
- HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须在多线程访问时显式同步对 HashSet 的并发访问。
- 集合元素值可以是null
- 不允许有重复元素的集合
由于HashSet没有下标所以不能用get()方法获取值
for (String i : set) {
System.out.println(i);
}
更多方法 : HashSet方法
LinkedHashSet
LinkedHashSet是HashSet的一个子类,具有HashSet的特性,也是根据元素的hashCode值来决定元素的存储位置。但它使用链表维护元素的次序,元素的顺序与添加顺序一致。由于LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet,但在迭代访问Set里的全部元素时由很好的性能。
更多方法 : LinkedHashSet方法
TreeSet
TreeSet时SortedSet接口的实现类,TreeSet可以保证元素处于排序状态,它采用红黑树的数据结构来存储集合元素。TreeSet支持两种排序方法:自然排序和定制排序,默认采用自然排序。
package listMapTest;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
//初始化
Set<Integer> sets = new TreeSet<>();
sets.add(111);
sets.add(222);
sets.add(333);
sets.add(444);
sets.add(555);
//遍历
for (Integer integer : sets) {
System.out.println(integer);
}
}
}
更多方法: TreeSet方法.
list集合
List集合代表一个有序、可重复集合,集合中每个元素都有其对应的顺序索引。List集合默认按照元素的添加顺序设置元素的索引,可以通过索引(类似数组的下标)来访问指定位置的集合元素。
ArratList
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。
实例
- 基础操作
package csdnTest;
import java.util.ArrayList;
public class ListTest {
public static void main(String[] args) {
//初始化 ArrayList<E> 尖括号中放引用数据类型
ArrayList<String> sites = new ArrayList<String>();
//添加元素
sites.add("zhangsan");
sites.add("lisi");
sites.add("wangwu");
sites.add("wangcai");
// 访问第二个元素,ArratList下标从0开始
System.out.println(sites.get(1));
//修改元素,第一个参数是下标,第二个是值
sites.set(2, "Wiki")
//删除元素,参数:下标
sites.remove(3);
//获取集合大小
sites.size();
}
}
- 遍历
//for遍历
for (int i = 0; i < sites.size(); i++) {
System.out.println(sites.get(i));
}
//for-each遍历
for (String i : sites) {
System.out.println(i);
}
//迭代器遍历
Iterator ite=list.iterator();
while(ite.hasNext()){
//调用一个next就读取一个元素
(转型)ite.next();
}
- ArrayList 常用方法
方法 | 描述 |
---|---|
add() | 将元素插入到指定位置的 arraylist 中 |
addAll() | 添加集合中的所有元素到 arraylist 中 |
clear() | 删除 arraylist 中的所有元素 |
clone() | 复制一份 arraylist |
contains() | 判断元素是否在 arraylist |
get() | 通过索引值获取 arraylist 中的元素 |
indexOf() | 返回 arraylist 中元素的索引值 |
removeAll() | 删除存在于指定集合中的 arraylist 里的所有元素 |
remove() | 复除 arraylist 里的单个元素 |
size() | 返回 arraylist 里元素数量 |
isEmpty() | 判断 arraylist 是否为空 |
toArray() | 将 arraylist 转换为数组 |
forEach() | 遍历 arraylist 中每一个元素并执行特定操作 |
更多方法:: ArrayList方法
LinkedList
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。
Java LinkedList(链表) 类似于 ArrayList,是一种常用的数据容器
与 ArrayList 相比,LinkedList 的增加和删除对操作效率更高,而查找和修改的操作效率较低。
以下情况使用 ArrayList :
- 频繁访问列表中的某一个元素。
- 只需要在列表末尾进行添加和删除元素操作。
以下情况使用 LinkedList :
- 你需要通过循环迭代来访问列表中的某些元素。
- 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
实例
- 基础操作
package csdnTest;
import java.util.LinkedList;
public class ListTest {
public static void main(String[] args) {
//初始化
LinkedList<String> sites = new LinkedList<String>();
sites.add("zhangsan");
sites.add("lisi");
sites.add("wangwu");
sites.add("wangcai");
// 使用 addFirst() 在集合第一位添加元素
sites.addFirst("Wiki");
// 使用 addLast() 在尾部添加元素
sites.addLast("Wiki");
// 使用 removeFirst() 移除第一个元素
sites.removeFirst();
// 使用 removeLast() 移除尾部元素
sites.removeLast();
// 使用 getFirst() 获取头部元素
sites.getFirst();
// 使用 getLast() 获取尾部元素
sites.getLast();
}
}
- 遍历
for (int size = sites.size(), i = 0; i < size; i++) {
System.out.println(sites.get(i));
}
for (String i : sites) {
System.out.println(i);
}
更多方法: LinkedList方法
Vector
与ArrayList相似,但是Vector是同步的。所以说Vector是线程安全的动态数组。它的操作与ArrayList几乎一样。
Vector<String> sites=new Vector<String>();
方法: Vector方法.
Stack
Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。
方法 | 描述 |
---|---|
push() | 入栈 |
pop() | 弹出顶元素 |
empty() | 可以检测stack内是否为空,返回true为空,返回false为非空 |
search() | 检测一个元素在堆栈中的位置 |
peek() | 得到栈顶的元素 |
方法: Stack方法.
Map集合
- Map接口采用键值对Map<K,V>的存储方式。
- key和value可以是任意引用类型的数据。key值不允许重复,可以为null。
- 如果添加key-value对时Map中已经有重复的key,则新添加的value会覆盖该key原来对应的value。
注意: Map 没有继承 Collection 接口, Map 提供 key 到 value 的映射,你可以通过“键”查找“值”。一个 Map 中不能包含相同的 key ,每个 key 只能映射一个 value 。 Map 接口提供 3 种集合的视图, Map 的内容可以被当作一组 key 集合,一组 value 集合,或者一组 key-value 映射。
常用方法:
HashMap
- HashMap 是一个最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。
HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null; - HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力。
-
HashMap和HashTable的区别
- HashMap是线程不安全,HashTable是线程安全的
- HashMap可以使用null值最为key或value;Hashtable不允许使用null值作为key和value,如果把null放进HashTable中,将会发生空指针异常。
-
HashMap实例
package listMapTest;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class TestMap {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
//放入键值对
map.put(1, "aaa");
map.put(2, "bbb");
map.put(3, "ccc");
map.put(4, "ddd");
//键无序,并且不能重复
//map.put(4, "eee");
//值可以重复
//map.put(5, "ddd");
//map.put(6, "ddd");
//map.put(7, "ddd");
//通过键获取值
String value = map.get(5);
System.out.println(value);
//获取所有的键
Set<Integer> sets = map.keySet();
//直接循环键
for (Integer i : sets) {
System.out.println(i + " " + map.get(i));
}
//获取所有的值
Collection<String> cs = map.values();
for (String s : cs) {
System.out.println(s);
}
}
}
更多方法: HashMap
TreeMap
TreeMap是SortedMap的实现类,是一个红黑树的数据结构,每个key-value对作为红黑树的一个节点。TreeMap存储key-value对时,需要根据key对节点进行排序。
方法: TreeMap
集合框架总结
Map总结
- HashMap 非线程安全
- HashMap:基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals()[可以重写hashCode()和equals()]。
- TreeMap:非线程安全基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。
List和Set总结
- List,Set都是继承自Collection接口,Map则不是
- List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)
- Set和List对比:
Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。