黑马程序员--第九篇 集合
第九篇 集合
很高兴,今天学习了集合。那么什么事集合呢?又为何要引进集合呢?
l 为什么出现集合类?
- 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java就提供了集合类。
l 数组和集合类同是容器,有何不同?
- 数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。
l 集合类的特点
- 集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
首先我们先熟悉Collection集合,他是所有集合的父类。下面了解一下他的成员方法:
l boolean add(E e)
l boolean remove(Object o)
l void clear()
l boolean contains(Object o)
l boolean isEmpty()
l int size()
l boolean addAll(Collection c)
l boolean removeAll(Collection c)
l boolean containsAll(Collection c)
l boolean retainAll(Collection c)
l Object[] toArray()
- 把集合转成数组,可以实现集合的遍历
l Iterator iterator()
- 迭代器,集合的专用遍历方式
而每个集合的底层数据结构可能是不一样的,所以我们需要了解一下数据结构的种类:
l 栈
l 队列
l 数组
l 链表
l 树
l 哈希表
特点:A:栈 先进后出
B:队列 先进先出
C:数组 查询快,增删慢
D:链表 查询慢,增删快
下面是collection及其子类的架构图:
由于需求不同,Java就提供了不同的集合类。这多个集合类的数据结构不同,但是它们都是要提供存储和遍历功能的,
我们把它们的共性不断的向上提取,最终就形成了集合的继承体系结构表。
Collection
|--List 有序,可重复
|--ArrayList
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高
|--Vector
底层数据结构是数组,查询快,增删慢。
线程安全,效率低
|--LinkedList
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高
|--Set 无序,唯一
|--HashSet
底层数据结构是哈希表。
如何保证元素唯一性的呢?
依赖两个方法:hashCode()和equals()
开发中自动生成这两个方法即可
|--LinkedHashSet
底层数据结构是链表和哈希表
由链表保证元素有序
由哈希表保证元素唯一
|--TreeSet
底层数据结构是红黑树。
如何保证元素排序的呢?
自然排序
***比较器排序(这个比较重要,开发中常用)
如何保证元素唯一性的呢?
根据比较的返回值是否是0来决定
4:针对Collection集合我们到底使用谁呢?(掌握)
唯一吗?
是:Set
排序吗?
是:TreeSet
否:HashSet
如果你知道是Set,但是不知道是哪个Set,就用HashSet。
否:List
要安全吗?
是:Vector
否:ArrayList或者LinkedList
查询多:ArrayList
增删多:LinkedList
如果你知道是List,但是不知道是哪个List,就用ArrayList。
如果你知道是Collection集合,但是不知道使用谁,就用ArrayList。
如果你知道用集合,就用ArrayList。
5:在集合中常见的数据结构(掌握)
ArrayXxx:底层数据结构是数组,查询快,增删慢
LinkedXxx:底层数据结构是链表,查询慢,增删快
HashXxx:底层数据结构是哈希表。依赖两个方法:hashCode()和equals()
TreeXxx:底层数据结构是二叉树。两种方式排序:自然排序和比较器排序
//这是集合的操作步骤:分为4步.
A:创建集合对象
B:创建元素对象
C:把元素添加到集合
D:遍历集合
public class CollectionDemo {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
//创建并添加元素
c.add("hello");
c.add("world");
c.add("java");
//遍历集合
Iterator it = c.iterator();
while(it.hasNext()) {
String s =(String) it.next(); //这个需要强转,以后会学习 泛型
System.out.println(s);
}
}
}
其实List集合的遍历方式有2种,还有一种是
//size()和get()方法结合。
for(int x=0; x<list.size(); x++) {
String s =(String) list.get(x);
System.out.println(s);
}
List的子类特点
ArrayList
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
Vector
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
LinkedList
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
另外下面是集合还要掌握的:
泛型(掌握)
(1)泛型概述
是一种把明确类型的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。
(2)格式:
<数据类型>
注意:该数据类型只能是引用类型。
(3)好处:
A:把运行时期的问题提前到了编译期间
B:避免了强制类型转换
C:优化了程序设计,解决了黄色警告线问题,让程序更安全
(4)泛型的前世今生
A:泛型的由来
Object类型作为任意类型的时候,在向下转型的时候,会隐含一个转型问题
B:泛型类
C:泛型方法
D:泛型接口
E:泛型高级通配符
?
? extends E
? super E
(5)我们在哪里使用呢?
一般是在集合中使用。
3:增强for循环(掌握)
(1)是for循环的一种
(2)格式:
for(元素的数据类型 变量名 : 数组或者Collection集合的对象) {
使用该变量即可,该变量其实就是数组或者集合中的元素。
}
(3)好处:
简化了数组和集合的遍历
(4)弊端
增强for循环的目标不能为null。建议在使用前,先判断是否为null。
4:静态导入(了解)
(1)可以导入到方法级别的导入
(2)格式:
import static 包名....类名.方法名;
(3)注意事项:
A:方法必须是静态的
B:如果多个类下有同名的方法,就不好区分了,还得加上前缀。
所以一般我们并不使用静态导入,但是一定要能够看懂。
5:可变参数(掌握)
(1)如果我们在写方法的时候,参数个数不明确,就应该定义可变参数。
(2)格式:
修饰符 返回值类型 方法名(数据类型... 变量) {}
注意:
A:该变量其实是一个数组名
B:如果一个方法有多个参数,并且有可变参数,可变参数必须在最后
(3)Arrays工具类的一个方法
asList()把数组转成集合。
注意:这个集合的长度不能改变。
最后我想增加一种比较独特的集合:Map
(1)将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
(2)Map和Collection的区别?
A:Map 存储的是键值对形式的元素,键唯一,值可以重复。夫妻对
B:Collection 存储的是单独出现的元素,子接口Set元素唯一,子接口List元素可重复。光棍
(3)Map接口功能概述
A:添加功能 V put(K key,V value)
B:删除功能 V remove(Object key) ;void clear()
C:判断功能 boolean containsKey(Object key)
boolean containsValue(Object value)
boolean isEmpty()
D:获取功能
E:长度功能int size()
(4)Map集合的遍历的两种方式:
A:键找值(这一种我们用得比较多)
a:获取所有键的集合
b:遍历键的集合,得到每一个键
c:根据键到集合中去找值
代码如下:
Set<String> set = hm.keySet();
for(String key : set) {
String value = hm.get(key);
System.out.println(key+"---"+value);
}
B:键值对对象找键和值
a:获取所有的键值对对象的集合
b:遍历键值对对象的集合,获取每一个键值对对象
c:根据键值对对象去获取键和值
代码如下:
Set<Map.Entry<String,String>> set2 = hm.entrySet();
for(Map.Entry<String,String> me : set2) {
String key = me.getKey();
String value = me.getValue();
System.out.println(key+"---"+value);
总结:集合主要掌握collection和Map集合及其子类。比较重要的就是遍历方式。
浙公网安备 33010602011771号