集合框架
以前在存储数据时用到的方法有:
- 变量:局部变量和成员变量
- 数组:存入多个同类型的数据
- 类:存入变量和方法,方便调用
- 对象数组:通过new一个构造方法,可以快速创建多个不同的对象。解决了重复写多个变量来定义。
集合框架解决了数组不可变的问题(集合也是用数组写的方法,当到达一定长度是,增加数组的长度)
-
Collection接口存储一组不唯一,无序的对象
-
List接口存储一组不唯一,有序(插入顺序)的对象
-
Set接口存储一组唯一,无序的对象
-
Mpa接口存储一组键值对象,提供key到value的映射
List接口的实现类
ArrayList实现了长度可变的数组,在内存中分配连续的空间。遍历元素和随机访问元素的效率比较高。
LinkedList采用链表存储方式。插入、删除元素时效率比较高
ArrayList常用方法
ArrayList<存储的数据的类型> 集合名 = new ArrayList<存储的数据的类型>();
- boolean add(Object object); 向列表中追加元素
- void add(int index,Object object); 向列表中的指定索引添加元素
- int size(); 获取列表的长度/元素个数
- Object get(int index); 根据索引获取对应的元素
- boolean contains(Object obj); 判断是否包含某个元素
- boolean remove(Object obj); 删除指定的元素
- Object remove(int index); 根据索引删除元素 且返回被删除的元素值
常用接口还有:
clear(); 清空数组
isEmpty(); 判断是否为空
集合里存只能存对象,存基本数据类型是JVM自动包装。
遍历方法:
for | 高级for | Iterator |
---|---|---|
基础 | 常用 | 操纵指针 |
LinkedList特有:
LinkedList数据结构是链表。
LinkedList linkedList = new LinkedList<>();
List接口中的API它也可以使用
- void addFirst(Object obj); 将元素添加到集合中第一个
- void addLast(Object obj); 将元素添加到集合中的最后一个
- Object getFirst(); 获取第一个元素
- Object getLast(); 获取最后一个元素
- Object removeFirst(); 删除第一个元素
- Object removeLast(); 删除最后一个元素
遍历方法:
for | 高级for | Iterator |
---|---|---|
基础 | 常用 | 操纵指针 |
Set接口
Set接口存储一组唯一,无序的对象
HashSet是Set接口常用的实现类
Set中存放的是对象的引用
Set接口不存在get()方法
增强型for循环遍历
Iterator遍历
了解ArrayList和LinkedList的区别?(面试题)
ArrayList:
底层是数组结构,在遍历或随机查找时比较快;但在添加或删除效率较LinkedList低,因为一个变动,就换导致多个数组的向前或向后移动。
LinkedList:
底层是链表结构,链表结构存储每一个元素由两部分组成,数据域和指针域,它没有索引。多个元素之间,双联前后连接。 因为没有索引,所以查找比较慢
,因为是链表结构,所以在增加或删除元素,波及的范围小,所以效率相比ArrayList高。
ArrayList的索引是固定的。类似于座位号 。
LinkedList的索引是根据元素位置计算出来的,并非固定的。
Set集合存取数据
特点:无序
唯一
HashSet
它的实现是根据hashCode()和equals()来做的比较。
遍历方法:
高级for | Iterator |
---|---|
常用 | 操纵指针 |
迭代器Iterator
Iterator(迭代器)模式又称Cursor(游标)模式,用于提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
// 创建迭代器
Iterator<String> itor = keys.iterator();
// 指针依次查找是否有内容
while(itor.hasNext()) {
// 返回键内容
String key = itor.next();
// 根据键返回值
String value = countries.get(key);
System.out.println(key+"-"+value);
}
Map接口
方法写上
看源码
Collections工具
-
Collections.max(list); // 查找集合中的最大值
-
Collections.min(list);// 查找集合中的最小值
-
Collections.sort(list);// 对集合进行升序排序
-
Collections.reverse(list); // 对集合进行反转
-
int binarySearch(集合,要查找的元素); 查找指定的键
-
void shuffle(集合); 打乱集合元素顺序
Comparable()重写
public int compareTo(Object o) {
Student stu = (Student)o;
if (this.score == stu.score) {
return 0;
}else if(this.score < stu.score){
return 1;
}else if(this.score > stu.score) {
return -1;
}
return 0;
}
return 1; 降
return 0;默认降
return -1; 升
Map接口的使用
HashMap<key,value>
Hashtable -> Properties
键是唯一的
常用API
- void put(Object key,Object value); 存储键值对
- Object get(Object key); 根据键获取值
- int size(); 获取集合中的键值对数量
- boolean containsKey(Object key); 是否包含指定的键
- boolean containsValue(Object value); 是否包含指定的值
- Set keySet(); 获取所有键的集合
- Collection values(); 获取所有值的集合
- Object remove(Object key); 根据键删除值并返回被删除的值
- boolean isEmpty(); 判断是否是空集合
- void clear(); 清空集合内容
遍历方法:
高级for | Iterator | 条目 |
---|---|---|
常用 | 操作指针,先keySet | entry |
了解HashMap和Hashtable的区别(面试题)
相同点:
- HashMap和Hashtable都是Map接口的实现,都可以实现键值对存储。
不同点:
-
HashMap键值存储都可以为Null,如果键为null则只能存储一次。
Hashtable键值存储都不允许为Null。
-
HashMap线程不安全,效率高。
Hashtable线程安全,效率低。
遍历方法
/**增强for遍历*/
public void for1(HashMap<String,String> hashMap) {
Set<String> keySet = hashMap.keySet();
for (String key : keySet) {
String value = hashMap.get(key);
System.out.println(+key+"\t"+value);
}
}
/**迭代器遍历*/
public void for2(HashMap<String,String> hashMap) {
Set<String> keySet = hashMap.keySet();
Iterator<String> itor = keySet.iterator();
while (itor.hasNext()) {
String key = itor.next();
String value = hashMap.get(key);
System.out.println(+key+"\t"+value);
}
}
/**条目遍历*/
public void for3(HashMap<String,String> hashMap) {
Set<Entry<String,String>> entrySet = hashMap.entrySet();
for (Entry<String,String> entry : entrySet) {
System.out.println(entry.getKey()+"\t"+entry.getValue());
}
}
泛型的基本使用
JDK1.5才出现的
还有包装类、注解、泛型等
-
在集合中用泛型声明元素数据类型 泛型必须是引用数据类型(包装类型)且不用强制类型转换
// 没有泛型要强转且可以添加任意类型 countries.put("法兰西共和国"); countries.put(123); countries.put(一个对象); for (Object obj : set) { NewsTitle title = (NewsTitle)obj; System.out.println(title.getId()+"-"+title.getTitle()); } // 有就可以不用只能添加指定类型 countries.put("法兰西共和国"); countries.put(123); // 检查异常 for (NewsTitle title : set) { System.out.println(title.getId()+"-"+title.getTitle()); }
-
利用泛型将程序变得更加易扩展(通过泛型占位符来进行扩展)
public class Test<T> { private String field1; private String field2; // 不确定是什么类型的 private T field3; } // 接收多个参数,转变为数组 Arrays.asList(T... a);