在学习集合之前、我们通常所用的容器是数组。
但是数组的使用是有很多限制的,比如数组的长度是固定的、且只能存储基本数据类型。
而集合中存储的是对象,且对象的类型可以不同,在对象的数量未知时很适合使用。
在需要遍历时,集合除了可以采用for或者增强for,还有一种方式,就是使用迭代器。
迭代器是一个实现Iterator接口或ListIterator接口的对象,可以通过循环来得到或删除集合中的元素。
关于集合类的问题、在很多公司面试时也会经常遇到。
关于集合类有一些重要的接口:
- List接口 元素有序、可重复。
- Set接口 元素不可重复。
- Map接口 利用键值对(key-value)存储,key必须唯一。
- ArrayList 基于数组实现,因此查询效率高,线程不安全.
- LinkedList 基于双链表实现,因此增删效率高,线程不安全。
- Vector 本质与ArrayList相同,但加入了线程安全,因此效率要比ArrayList降低很多。
- ArrayList的初始容量为10,扩容规则为:扩容后容量 = 原始容量*1.5 + 1;所以第一次扩容后的容量为16
- LinkedList是双向链表,没有初始容量,也就没有扩容机制。
- Vector需要提的是,虽然ArrayList的扩容倍数是1.5,但是Vector的扩容倍数是2。
在这贴一个ArrayList的练习示例
package gzx;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* LinkedList和ArrayList的用法类似,但是功能不同。
* 以下是使用ArrayList时,三种遍历方式
*/
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Hello");
list.add("Java");
//第一种遍历
for(String str : list){
System.out.println(str);
}
//第二种遍历
String[] str1 = new String[list.size()];
list.toArray(str1);
for(String str : str1){
System.out.println(str);
}
/*
for(int i = 0; i < str1.length; i++){
System.out.println(str1[i]);
}
此写法同上
*/
//第三种,也就是集合类中最常用的方法
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
下面继续说Set
- HashSet 底层用哈希表实现,无序。
- TreeSet 底层用二叉树实现,有序。
关于Set的用途,用一道很简单的笔试题来看吧
题目来源:牛客网(京东2017年校招编程题其中一道)
package gzx;
import java.util.Iterator;
import java.util.Scanner;
import java.util.TreeSet;
/**
* 根据题意,需要去重,还需要排序,很容易想到使用TreeSet
*/
public class SetTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
TreeSet<Integer> set = new TreeSet<Integer>();
int n1 = sc.nextInt();
int n2 = sc.nextInt();
String str = null;
for(int i = 0; i<n1; i++) {
set.add(sc.nextInt());
}
for(int i = 0; i<n2; i++) {
set.add(sc.nextInt());
}
Iterator<Integer> it = set.iterator();
while(it.hasNext()) {
System.out.print(it.next());
if(it.hasNext())
System.out.print(" ");
}
}
}
最后说一下Map
最常用的是HashMap、TreeMap,其他的会以后再更新。
- HashMap 基于哈希表实现,线程不安全。 允许null为value
- TreeMap 基于红黑二叉树实现,线程不安全。不允许null为value
- HashMap的初始容量是16,加载因子为0.75,扩容机制是 新容量 = 旧容量 * 2
还是用示例代码来看一下使用方式
package gzx;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* 示例程序为map的多种遍历方式
*/
public class MapTest {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("1","value1");
map.put("2","value2");
map.put("3","value3");
// 第一种,通过Map.keySet遍历
for(String key : map.keySet()){
System.out.println("key= "+ key + " and value= " + map.get(key));
}
//第二种,通过Map.entry使用iterator
Iterator<Map.Entry<String,String>> it = map.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String,String> entry = it.next();
System.out.println("key= "+entry.getKey() + " and Value= " + entry.getValue());
}
//第三种,容量大的时候,推荐此种方式
for(Map.Entry<String,String> entry : map.entrySet()){
System.out.println("key: "+ entry.getKey()+" and Value= "+entry.getValue());
}
//第四种,可遍历所有的value,不能遍历key
for (String s : map.values()){
System.out.println("value= " + s);
}
}
}
集合这部分是在Java开发中经常会用到的,除了用法还要了解每个集合类的内部机制。
本篇博客会不定时持续更新。