目标
掌握集合的接口和实现类的概念特点。
熟练运用迭代器。
了解Collection接口中的常用方法。
掌握每个集合对象的创建、添加元素,取元素,遍历集合
集合一图流
Map一图流
总结
ArrayList:底层是数组。
LinkedList:底层是双向链表。
Vector:底层是数组,线程安全的,效率较低,使用较少。
HashSet:底层是HashMap,放到HashSet集合中的元素等同于放在HashMap集合key部分了。
TreeSet:底层是TreeMap,放在TreeSet集合中的元素等同于放到TreeMap集合Key部分。
HashMap:底层是哈希表。
Hashtable:底层是哈希表,线程安全,效率较低,使用较少。
Properties:继承Hashtable,是线程安全的,并且key和value只能存储字符串String
TreeMap:底层是二叉数。TreeMap集合的key可以自动按照大小顺序排序。
List集合存储元素的特点:有序可重复
Set集合存储元素的特点:无序不可重复
SortedSet集合存储元素特点:无序不可重复,可以按照大小顺序排序。
Collection的常用方法
boolean add(Object e) 向集合添加元素。
int size() 获取集合中元素的个数。
void clear() 清空集合
boolean contains(Object o) 判断当前集合中是否包含元素o,包含返回true,反之亦然;底层会调用equals
boolean remove(Object o) 删除集合中的某个元素;底层会调用equals
boolean isEmpty() 判断该集合元素的个数是否为0
Object[] toArray() 调用这个方法可以把集合转换为数组。
集合的迭代器
执行原理
借用一下我最爱的动力节点杜老师的图。
public class CollectionTest01 {
public static void main(String[] args) {
Collection c = new HashSet();
c.add("abc");
c.add("def");
c.add(100);
c.add(new Object());
//用集合创建出迭代器。
Iterator it = c.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}
输出
用迭代器删除元素
用迭代器删除元素是用迭代器里面的remove方法,不是用Collection内的remove方法;
public class CollectionTest01 {
public static void main(String[] args) {
Collection c = new HashSet();
c.add("abc");
c.add("def");
c.add(100);
c.add(new Object());
//用集合创建出迭代器。
Iterator it = c.iterator();
System.out.println(c.size());
System.out.println("----------------");
while (it.hasNext()){
it.next();//这里必须要调用next()方法,没有next()方法会报错
it.remove();
}
System.out.println(c.size());
}
}
输出
List接口
常用方法
void add(int index,Object element) 添加
Object get(int index) 获取
Object remove(int index) 删除
Object set(int index,Object element) 修改
int indexOf(Object o) 第一次出现该元素的下标
int lastIndexOf(Object 0) 最后一次出现该元素的下标
ArrayList
public class CollectionTest01 {
public static void main(String[] args) {
List c = new ArrayList();//创建数组
List d = new ArrayList(100);//指定初始化容量
c.add("def");
/*
list可以指定位置插入元素,前提是这个位置存在。如果你刚new出来,
有效的索引值只能是 0。试图在索引为 1 的位置插入元素 “abc”,
会抛出IndexOutOfBoundsException异常。
*/
c.add(1, "abc");//add方法
c.add(100);
c.add(new Object());
System.out.println(c);
System.out.println("----------------");
//删除指定下标元素
c.remove(0);//remove方法
System.out.println(c);
System.out.println("----------------");
//修改指定位置元素
c.set(2,"lww");//set方法
System.out.println(c);
System.out.println("----------------");
//用循环可以该List集合,因为有下标
//而Set没有下标,Set不能循环遍历
for (int i = 0;i < c.size();i++){
Object object = c.get(i);
System.out.println(object);
}
}
}
LinkedList
LinkedList没有初始化容量
最初这个链表中没有任何元素,first和last引用都是null
代码和上面差不多
public class CollectionTest01 {
public static void main(String[] args) {
List c = new LinkedList();//创建数组 底层是双向链表
c.add("def");
/*
list可以指定位置插入元素,前提是这个位置存在。如果你刚new出来,
有效的索引值只能是 0。试图在索引为 1 的位置插入元素 “abc”,
会抛出IndexOutOfBoundsException异常。
*/
c.add(1, "abc");//add方法
c.add(100);
c.add(new Object());
System.out.println(c);
System.out.println("----------------");
//删除指定下标元素
c.remove(0);//remove方法
System.out.println(c);
System.out.println("----------------");
//修改指定位置元素
c.set(2,"lww");//set方法
System.out.println(c);
System.out.println("----------------");
//用循环可以该List集合,因为有下标
//而Set没有下标,Set不能循环遍历
for (int i = 0;i < c.size();i++){
Object object = c.get(i);
System.out.println(object);
}
}
}
Vector
代码和上面差不多
public class CollectionTest01 {
public static void main(String[] args) {
List c = new Vector();
c.add("def");
/*
list可以指定位置插入元素,前提是这个位置存在。如果你刚new出来,
有效的索引值只能是 0。试图在索引为 1 的位置插入元素 “abc”,
会抛出IndexOutOfBoundsException异常。
*/
c.add(1, "abc");
c.add(100);
c.add(new Object());
System.out.println(c);
System.out.println("----------------");
//删除指定下标元素
c.remove(0);
System.out.println(c);
System.out.println("----------------");
//修改指定位置元素
c.set(2,"lww");
System.out.println(c);
System.out.println("----------------");
//用循环可以该List集合,因为有下标
//而Set没有下标,Set不能循环遍历
for (int i = 0;i < c.size();i++){
Object object = c.get(i);
System.out.println(object);
}
}
}
Collections.synchronizedList();//这个方法可以将非线程安全的转为线程安全的
List c = new ArrayList();
c.add("def");
c.add(1, "abc");
c.add(100);
c.add(new Object());
//这个方法可以将非线程安全的转为线程安全的
Collections.synchronizedList(c);
三种遍历集合的方法
迭代器、for循环、增强for循环。
public class CollectionTest01 {
public static void main(String[] args) {
List<String> c = new ArrayList<>();
c.add("def");
c.add("abc");
c.add("100");
c.add("1456");
Iterator it = c.iterator();
//迭代器遍历
while (it.hasNext()){
System.out.println(it.next());
}
System.out.println("---------------");
//for循环
for (int i = 0;i < c.size();i++){
System.out.println(c.get(i));
}
System.out.println("---------------");
//增强for循环
for(String s : c){
System.out.println(s);
}
}
}
set接口
HashSet
无序不可重复。
public class CollectionTest01 {
public static void main(String[] args) {
Set<String> c = new HashSet<>();
c.add("def");
c.add("abc");
c.add("100");
c.add("1456");
c.add("1456");
c.add("1456");
Iterator it = c.iterator();
//迭代器遍历
while (it.hasNext()){
System.out.println(it.next());
}
System.out.println("---------------");
}
}
输出
TreeSet
无序不可重复
但是按大小顺序排序。
public class CollectionTest01 {
public static void main(String[] args) {
Set<String> c = new TreeSet<>();
c.add("a");
c.add("b");
c.add("c");
c.add("d");
c.add("c");
c.add("e");
Iterator it = c.iterator();
//迭代器遍历
while (it.hasNext()){
System.out.println(it.next());
}
}
}
输出:
Map接口
常用方法
V put() 向Map集合中添加键值对
V get(Object ky) 通过key获取value
V remove(Object key) 通过key删除键值对
void clear() 清空Map集合
int size() 获取Map集合中的键值对的个数
boolean isEmpty() 判断Map集合中的元素个数是否为0
boolean containsKey(Object key) 判断Map中是否包含某个key
boolean containsValue(Object value) 判断Map中是否包含某个value
Set<k> keySet() 获取Map集合中的所有key
Collection<V> values() 获取Map集合中所有的value,返回一个collection。
HashMap
public class CollectionTest01 {
public static void main(String[] args) {
//创建Map
Map<Integer, String> map = new HashMap();
//添加元素
map.put(1,"zhangsan");
map.put(2,"lisi");
map.put(3,"wangwu");
map.put(4,"zhaoliu");
System.out.println("原集合"+map);//{1=zhangsan, 2=lisi, 3=wangwu, 4=zhaoliu}
//获取某个元素
String s = map.get(2);
System.out.println("获取元素为:"+s);//lisi
//修改元素,没有出现在常用方法,应该不常用。
map.replace(1,"zhangzhang");
System.out.println("修改后集合"+map);//{1=zhangzhang, 2=lisi, 3=wangwu, 4=zhaoliu}
//删除元素
map.remove(2);
System.out.println("删除后集合"+map);//{1=zhangzhang, 3=wangwu, 4=zhaoliu}
//获取集合元素个数
System.out.println("集合元素个数为:"+map.size());//3
//判断集合是否为空
System.out.println("判断集合是否为空:"+map.isEmpty());//false
}
}
遍历Map集合的方法
第一种方式
1、将Map集合转为Set集合
2、迭代器遍历Set集合,通过get方法获取Map对应的Value。
或者用foreach遍历set集合,通过get方法获取Map对应的Value。
//创建Map
Map<Integer, String> map = new HashMap();
//添加元素
map.put(1,"zhangsan");
map.put(2,"lisi");
map.put(3,"wangwu");
map.put(4,"zhaoliu");
//获取所有的key,转换为set集合
Set<Integer> keys = map.keySet();
//通过迭代器遍历
Iterator<Integer> it = keys.iterator();
while (it.hasNext()){
Integer key = it.next();
System.out.println(key + "=" + map.get(key));
}
System.out.println("---------------");
//foreach也可以
for (Integer key : keys){
System.out.println(key + "=" + map.get(key));
}
第二种方式
Set<Map.Entry<k,v>> entrySet();
将Map集合全部转为Set集合
然后迭代器遍历或者foreach遍历。
//创建Map
Map<Integer, String> map = new HashMap();
//添加元素
map.put(1,"zhangsan");
map.put(2,"lisi");
map.put(3,"wangwu");
map.put(4,"zhaoliu");
//Map集合全部转为Set集合
Set<Map.Entry<Integer, String>> set = map.entrySet();
//变成set集合正常遍历就行
Iterator<Map.Entry<Integer, String>> it = set.iterator();
while(it.hasNext()){
Map.Entry<Integer, String> node = it.next();
System.out.println(node.getKey() + "=" + node.getValue());
}
//这种方式效率较高。
for(Map.Entry<Integer, String> node1 : set){
System.out.println(node1.getKey() + "===>" + node1.getValue());
}
哈希表的数据结构
HashMap底层是一个一维数组。
存储的是静态的内部类HashMap.Node
杜老师的图
如果你的元素要放在HashMap的key或HashSet中,这个元素的hashCode()方法和equals()方法要重写。(其实我们写一个类,重写了equals一般也会同步重写hashcode)
hashCode()判断位置
equals()判断是否要覆盖。
Hashtable
Hashtable的key可以为null吗?
Hashtable的key和value都不能为null
HashMap集合的key和value都可以为null
Hashtable方法都带有synchronized:线程安全的
但效率较低,且有其他方案,使用较少。
Hashtable和HashMap一样,底层是哈希表数据结构。
Hashtable的初始化容量是11,默认加载因子是:0.75f
Hashtable的扩容是:原容量 * 2 + 1
Properties类
//创建一个Properties
Properties properties = new Properties();
//存
properties.setProperty("url","1");
properties.setProperty("driver","2");
properties.setProperty("username","3");
properties.setProperty("password","4");
//取
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(url);//1
System.out.println(driver);//2
System.out.println(username);//3
System.out.println(password);//4
TreeMap
可以排序元素大小;
对String类也可以排序,按字典顺序升序。
对自定义的类也可以排序
第一种方法:需要自定义类实现Comparable接口,实现其中的compareTo方法。
比较规则:
返回0表示相同,value覆盖
返回>0,会继续在右子树上找。
返回<0,会继续在左子树上找。
第二种方法实现:比较器接口
代码演示:
public class TreeMapTest01 {
public static void main(String[] args) {
//在创建TreeSet的时候将比较器传进去
TreeSet<People> people = new TreeSet<>(new PeopleComparator());
people.add(new People(20));
people.add(new People(100));
people.add(new People(40));
people.add(new People(15));
for (People p : people){
System.out.println(p);
}
}
}
class People {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public People(int age) {
this.age = age;
}
@Override
public String toString() {
return "People{" +
"age=" + age +
'}';
}
}
//这里单独写一个比较器
class PeopleComparator implements Comparator<People>{
@Override
public int compare(People o1, People o2) {
//比较规则,按年龄排序
return o1.getAge() - o2.getAge();
}
}
输出