【Java学习笔记】类集框架
Java集合
概述
Java中集合可分为Set、List、Queue、Map四种,Set代表无序、不可重复的集合;List代表有序、重复的集合;Queue代表一种队列集合;Map代表具有映射关系的集合(键值对)。
1)集合类于数组的区别
- 数组既可以是基本类型的值,也可以是对象;
- 集合里只能保存对象(虽然集合里不能放基本类型的值,但Java支持自动装箱)。
2)集合继承关系图
Collection类
1)常用方法
No | 方法名称 | 说明 |
---|---|---|
1 | public boolean add(E e) | 向集合里添加一个普通元素 |
2 | public boolean addAll(Collection c) | 追加一个集合 |
3 | public void clear() | 清空集合 |
4 | public boolean contains(Object o) | 判断是否包含有指定的内容 |
5 | public boolean isEmpty() | 判断是否是空集合 |
6 | public boolean remove(Object o) | 删除对象 |
7 | public int size() | 取得集合中元素保存的个数 |
8 | public Object[] toArray() | 将集合变成对象数组保存 |
9 | Iterator iterator() | 为Iterator接口实例化 |
contains()与remove()方法需要equals()支持。Collection接口几乎不会使用了,而主要使用List(允许重复)与Set(不允许重复)子类。
List集合
大量的扩充了Collection接口的方法。
1)常用方法
No | 方法名称 | 说明 |
---|---|---|
1 | public E get(int index) | 取得索引编号的内容 |
2 | public E set(int index, E element) | 修改指定索引编号的内容 |
3 | public ListIterator listIterator() | 为ListIterator接口实例化 |
由于List本身是属于接口的,所以必须存在有子类(ArrayList或Vector)才能使用此接口进行操作。
2)ArrayList与Vector的区别?
No | 区别点 | ArrayList | Vector |
---|---|---|---|
1 | 推出时间 | JDK1.2推出 | JDK1.0推出 |
2 | 性能 | 采用异步处理 | 采用同步处理 |
3 | 数据安全 | 非线程安全 | 线程安全 |
4 | 输出 | Iterator、ListIterator、foreach | Iterator、ListIterator、foreach、Enumeration |
3)总结
- List中的数据保存顺序就是数据的添加顺序;
- List集合中可以保存有重复的元素;
- List子接口比Collection接口扩充了一个get()方法,使得List可以通过索引访问集合的元素内容;
- List选择子类就使用ArrayList。
Set集合
Set接口并不像List接口那样对Collection接口进行了扩充,而只是进行了简单的继承。
set集合类似一个罐子,程序可以依次把多个对象“丢进”Set集合,而Set集合通常不能记住元素的添加顺序。Set集合不允许包含相同的元素,如果试图将相同的元素加入同一个Set集合中,则添加操作失败。Set集合有HashSet、TreeSet和EnumSet三个实现类。
HashSet类
HashSet是Set接口的典型实现,大多数时候使用Set集合时就是使用这个实现类。HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。
1)特点
- 不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。
- HashSet不是同步的,如果多个线程同时访问和修改一个HashSet,则必须通过代码来保证其同步。
- 集合元素之可以是null。
- HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且这个对象的hashCode()方法返回值也相等。
LinkedHashSet类
LinkedHashSet集合同样也是根据元素的hashCode值来决定元素的存储位置,但他同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的。所以当我们遍历LinkedHashSet集合里的元素时,LinkedHashSet将会按元素的添加顺序来访问集合里的元素。
LinkedHashSet需要维护元素的插入顺序,所以性能略低于HashSet的性能。但在遍历Set里的全部元素时将有很好的性能。
TreeSet类
TreeSet类主要依靠Comparable接口中的compareTo()方法判断,如果返回的是0,那么它就会被认为是重复数据,不会被保存。
一般不会使用。
Map接口
用于保存一对关联数据(key = value),即键值对,可以使用Map接口实现此类数据的保存。可以通过key查找value。Map存放数据的目的主要是为了信息查找。
1)常用方法
No | 方法名称 | 说明 |
---|---|---|
1 | public V put(K key, V value) | 向集合中保存数据 |
2 | public V get(Objet key) | 根据key查找对应的value数据 |
3 | public Set |
HashMap
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put(null, 0); //可以存null
map.put("ONE", 1);
map.put("TWO", 2);
map.put("THREE", 3);
map.put("TWO", 22); //key重复项
System.out.println(map);
System.out.println(map.get("TWO")); //覆盖后的value值,返回22
System.out.println(map.get(null)); //返回0
System.out.println(map.get("FOUR")); //不存在的key值,返回null
//获得所有的Key,并输出
Set<String> set = map.keySet();
Iterator<String> it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
特点:
- HashMap集合时无序的;
- key重复时,旧的value会被新的value覆盖。
Hashtable
在JDK1.0时提供的
public static void main(String[] args) {
Map<String, Integer> map = new Hashtable<String, Integer>();
map.put("one", 1);
map.put("two", 2);
map.put("three", 3);
map.put("three", 3);
//错误
map.put("Four", null); //value不能为null
map.put(null, 4); //key不能为null
System.out.println(map);
}
Hashtable与HashMap使用起来是类似的,但Hashtable 的key与value都不能设置为null。
HashMap与Hashtable 的区别
No | 区别点 | HashMap | Hashtable |
---|---|---|---|
1 | 推出时间 | JDK1.2推出 | JDK1.0推出 |
2 | 性能 | 采用异步处理 | 采用同步处理 |
3 | 数据安全 | 非线程安全 | 线程安全 |
4 | 设置null | 允许key与value为null | 不允许key与value为null |
Map的输出问题
Map接口与并没有返回Iterator接口对象的方法,所以如果想要使用Iterator输出Map集合,还需要经过一定的转化。
1)Map.Entry
public static interface Map.Entry<K, V>
而在这个内部接口中,定义了两个get()与set()方法:
- public K getKey();
- public V getValue();
2)输出Map的步骤:
- 利用Map接口的entrySet()方法将Map集合变为Set集合,里边的泛型是Map.Entry;
- 利用Set集合中的iterator()方法将Set集合进行Iterator输出;
- 每一次Iterator循环去除的都是Map.Entry接口对象,利用此对象进行key与value的取出。
3)示例
public static void main(String[] args) {
Map<String, Integer> map = new Hashtable<String, Integer>();
map.put("ONE", 1);
map.put("TWO", 2);
map.put("THREE", 3);
//将Map集合变为Set集合,为了使用iterator()方法
Set<Map.Entry<String, Integer>> set = map.entrySet();
//创建iterator对象
Iterator<Map.Entry<String, Integer>> it = set.iterator();
//循环取出
while(it.hasNext()) {
Map.Entry<String, Integer> em = it.next();
System.out.println(em.getKey() + " = " + em.getValue());
}
}
Map集合中的key
当我们使用自定义的类型来做Map的key值时,一定要重写Object类之中的hashCode()与equals()方法,这有靠这两个方法才能够确定元素是否重复,才能够在Map中查找到。
所以在使用Map时,String类型是首选的key类型,尽量少用自定义的类型作为key。
集合的输出
主要支持四种输出方式:Iterator、ListIterator、Enumeration、foreach。以Iterator与Enumeration为主。
迭代输出——Iterator(核心)
Iterator接口也是Java集合框架的成员,它主要由用于遍历Collection集合中的元素,Iterator对象也被称为迭代器。修改迭代遍历Iterator的值对集合元素本身不会产生影响。
1)常用方法
No | 方法名称 | 说明 |
---|---|---|
1 | public boolean hasNext() | 如果被迭代的集合元素还没有被遍历完,则返回true |
2 | public Object next() | 返回集合里的下一个元素 |
2)遍历集合示例
public static void main(String[] args) {
//创建集合,并添加数据
List<String> book = new ArrayList<String>();
book.add("Compute Network");
book.add("Clean Code");
book.add("Java");
//迭代输出
Iterator it = book.iterator();
while(it.hasNext()) {
String bookName = (String)it.next;
System.out.println(bookName);
if(book.equals("Clean Code")) {
it.remove(); //将"Clean Code"从集合中移除
}
}
//遍历集合
book.forEach(str -> System.out.println(str));
//foreach输出
//ArrayList实现了get()方法,所以可以通过索引进行访问
for(int i =0; i < book.size(); i++) {
String str = book.get(i);
System.out.println(str);
}
}
3)双向迭代
Iterator只提供从前往后的迭代输出,而我们可以使用Iterator的子接口——ListIterator来实现从后向前的迭代输出。
No | 方法名称 | 说明 |
---|---|---|
1 | public boolean hasPrevious() | 判断是否有前一个元素 |
2 | public E previous() | 取得前一个元素 |
ListIterator是专门为List子接口定义的输出接口,它只能通过List来获得ListIterator的实例。
public static void main(String[] args) {
List<String> book = new ArrayList<String>();
book.add("Compute Network");
book.add("Clean Code");
book.add("Java");
ListIterator<String> it = book.listIterator();
System.out.println("由前向后进行输出:");
while(it.hasNext()) {
String bookName = (String)it.next();
System.out.println(bookName);
}
System.out.println("由后向前进行输出:");
while(it.hasPrevious()) {
String bookName = (String)it.previous();
System.out.println(bookName);
}
}
如果要想实现由后向前输出,必须得先由前向后输出。(如果将以上示例将输出代码的顺序交换,就会发生没有值的错误)
foreach输出
我最喜欢的还是foreach循环遍历,简洁。
public static void main(String[] args) {
//创建集合,并添加数据
…
for(Object obj : books) {
String bookName = (String)obj;
System.out.println(bookName);
}
}
Enumeration输出
在JDK1.0时所推出的输出接口
1)常用方法
NO | 方法名称 | 说明 |
---|---|---|
1 | public boolean hasMoreElements() | 判断是否有下一个元素 |
2 | public E nextElement() | 取出当前元素 |
取得Enumeration接口的实例只能通过Vector子类。
Collections工具类
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
Collections.addAll(list, "A","B","C","D"); //追加
Collections.reverse(list); //反转
System.out.println(list);
}
1)Collection与Collections的区别?
- Collection是集合操作的接口;
- Collections是结合操作的工具类,可以进行List、Set、Map集合的操作。
还没有评论,来说两句吧...