集合框架(一)
在之前的学习中,我们所知道的在java中的临时存储数据的有:
**变量:****(特点)只能存储单一数据
int arr = 10;
double num = 10.5;
**Array数组:**一组连续的相同数据类型的固定长度的有序储存空间
int[] arr = {12,33,14,15};
String[] arr1 = {"asd","zxc","qwe","poi"};
数组特点:
1、一组数据 | 2、想同数据类型 |
---|---|
3、有序 | 4、长度无法改变 |
类和对象(实体):
对象数组:它正在一定程度上解决了数据类型单一的问题
一、了解Java 集合框架结构
java集合框架:
Collection收集:(不要求有序且数据不唯一,可重复元素),顶级接口
List接口、(有序、可重复)
ArrayList(实现类)、
Linked List(实现类)
二、会使用ArrayList存储数据**
ArrayList<> List = new ArrayList<>();
1、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);
来自于ArrayList的父级接口们:
toArray(); // 转换为数组
clear();// 清除所有的元素
isEmpty();// 判断是否为空集合 / list.size() == 0
iterator();// 迭代器
public class Dame{
public static void main(String[] args){
List list = new ArrayList();
// 集合的添加
list.add("张三");
list.add("李四");
// 集合的修改
// 根据下标位修改
list.set(0,"张三丰");
// 集合的查找
// 对象信息强制转换为字符串
String name = (String)list.get(0); System.out.println(name);
System.out.Println(list,size());
// 集合的删除
// 删除:根据下标删除,也可以根据对象值删除
list.remove(2);
list.remove("张三")
// 集合清空,清空整个集合list.clear();
/*历方法有三种:*/
// 遍历数组
for(int i = 0;i < list,size();i ++){ System.out.println(list,get(i))
}
// 增强for
for(Object odj:list){ System.out.println(obj)
}
}
}
ArrayList优点:
1、末尾添加元素 |
---|
2、随机访问,或者是遍历 |
弊端:元素的位移(如果删除或者插入元素)程序操运行复杂
三、会使用LinkedList存储数据**
底层是(双向链表),存储空间不是连续的。
LinkedList linkedList = new LinkedList<>();
优势:插入元素,删除元素,非常方便,对其他元素没有影响
写法与ArrayList大致一样
public class Dame{
public static void main(String[] args){
List list = new LinkedList();
// 集合的添加
list.add("张三");
list.add("李四");
// 集合的修改
// 根据下标位修改
list.set(0,"张三丰");
//集合的查找
String name = (String)list.get(0); System.out.println(name);
System.out.Println(list,size());
// 集合的删除
// 删除:根据下标删除,也可以根据对象值删除
list.remove(2);
list.remove("张三")
// 集合清空,清空整个集合list.clear();
/*历方法有三种:*/
// 遍历数组
for(int i = 0;i < list,size();i ++){
System.out.println(list.get(i))
}
// 增强for
for(Object odj:list){ System.out.println(obj)
}
}
}
LinkedList扩展:
add(Object );// 追加在后面
addFirst(Object );// 追加在最前面
addLast();// 追加在最后面
getFirst(); // 获取第一个
getLast(); // 获取最后一个
removeFirst();// 删除最前面第一个
removeLast();// 删除末尾最后一个
public class Dame{
public static void main(String[] args){
// List list = new LinkedList 接口类型
// 扩展LinkedList,必须是自己构建自己
LinkedList list = new LinkedList();
// 扩展后可以调用的方法
list.add();// 追加在后面
list.addFirst();// 追加在最前面
list.addLast();// 追加在最后面
list.removeFirst();// 删除最前面第一个
list.removeLast();// 删除末尾最后一个
}
}
ArrayList和LinkedList的选用:
1、如果有大量的插入和删除元素的操作,用LinkedList |
---|
2、如果只是大量在末尾追加元素,然后元素进行遍历,就用ArrayList |
3、ArrayList底层是数组,LinkedList底层是链表 |
四、了解ArrayList和LinkedList的区别?(面试题)
ArrayList:查找快,增删慢
底层是数组结构,所以因为是数组,则拥有索引,在遍历或随机查找时比较快,但是又因为是数组,数组长度不可变,每一次增删都是要创建新的数组,比较慢。
LinkedList:
底层是链表结构,链表结构每一个元素由两部分组成,数据域和指针域,它没有索引。多个元素之间,通过指针域指向连接。因为没有索引,所以查找比较慢,但是因为是链表所以在增删时只需要切换指针指向即可(尤其首尾快)。
在我们使用时,发现ArrayList和LinkedList好像度拥有索引,为什么?
它们的索引不同!
ArrayList的索引是固定的。类似于座位号
LinkedList的索引是根据元素位置计算出来的,并非固定的
五、掌握使用Set存储数据
Set接口、(无序、不可重复)
常用:HashSet,
其实它实现唯一,是根据hashCode()和equals()来做的比较。
Set中是没有get方法的
特点:
1、存储速度快 | |
---|---|
2、没有顺序,不可重复,不能通过下标访问 |
public class Dame{
public static void main(String[] args){
Set set = new HashSet();
set.add("张三");
set.add("李四");
set.add("张三");
// ste.size();集合长度
System.out.println(set.size());
}
}
// 输出的结果是:2
// 修改元素
public class Dame{
public static void main(String[] args){
Set set = new HashSet();
set.add("张三");
set.add("李四");
set.add("张六");
// 修改元素,
/* set集合是没有下标位的,
想要修改,只能变相的先删除,然后再重新写入*/
set.remove("张六");
set.add("王五");
}
}
Set遍历
// 遍历 使用到Iterator(迭代器)接口
public class Dame{
public static void main(String[] args){
Set set = new HashSet();
set.add("张三");
set.add("李四");
set.add("张六");
set.add("王五");
// 方法一
// 遍历 使用迭代器遍历
Iterator<String> it = set.interator();
// 长度不确定,需要判断 ,
// hasNext();判断下列元素是否在集合中
// 如果为true 继续, 不为true就结束
while(in.hasNext()){
// next() 获取下一个元素
String str = (String)it.next();
System.out.println(str);
}
// 方法二 使用 增强for()
for(Object obj : set){
System.out.Println(obj);
}
}
}
// 输出的结果 和写人的顺序是不一样的,因为Set是无序
public class Demo {
public static void main(String[] args) {
// List系列集合 ArrayList LinkedList
List<String> list = Arrays.asList("hehe","xixi","heihei","haha");
// 创建Set集合
Set<String> set = new HashSet<>();
set.add("hehe");
set.add("xixi");
set.add("meme");
// 1.普通for循环 利用索引来遍历
/*for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
System.out.println(str);
}*/
// 2.增强for循环【推荐】 遍历出每一个元素值
/*for(String str : list) {
System.out.println(str);
}
System.out.println("-------------------");
for (String str : set) {
System.out.println(str);
}*/
// 3.迭代器
Iterator<String> iterator = list.iterator();
// iterator.hasNext() 判断是否有下一个元素
// iterator.next() 获取下一个元素
while(iterator.hasNext()) {
String value = iterator.next();
System.out.println(value);
}
System.out.println("---------------------");
Iterator<String> setIterator = set.iterator();
while(setIterator.hasNext()) {
String str = setIterator.next();
System.out.println(str);
}
}
}
六、Map接口:映射(一一映射)(键值对)
常用:
HashMap,<key ,vaule>
key == value (一个键key 对应一个值value )
常用:HashMap
void put(Object key,Object value);// 存储键值对
Object get(Object key);// 根据键获取值(键是唯一的)
int size();// 获取集合中的键值对数量
boolean containsKey(Object key);// 是否包含指定的键
boolean containsValue(Object value);// 是否包含指定的值
Set<Object> keySet();// 获取所有键的集合
Collection<Object>values();// 获取所有值的集合
Object remove(Object key);// 根据键删除值,会返回被删除的值
boolean isEmpty();// 判断是否是空集合
void clear();// 清空集合内容
/**
* 思路:
* 获取键集合
* 遍历键集合
* 根据键获取对应值
*/
public class Demo1 {
public static void main(String[] args) {
Map<String, String> hashMap = new HashMap<>();
hashMap.put("CN", "中国");
hashMap.put("RU", "俄国");
hashMap.put("UK", "英国");
// 获取键集合
Set<String> keySet = hashMap.keySet();
// 遍历键集合[推荐]
/*for (String key : keySet) {
// 根据键获取值
// keySet.get(key)
String value = hashMap.get(key);
System.out.println(key+" --> "+value);
}*/
// 迭代器遍历
Iterator<String> iterator = keySet.iterator();
while(iterator.hasNext()) {
String key = iterator.next();
String value = hashMap.get(key);
System.out.println(key+" --> "+value);
}
}
}
增加元素 .put(key,value);
删除元素 用remove(key);
读取单个元素 用get(key);
获取长度: size()
判断是否存在指定的key .containsKey(key)
判断是否存在指定的value .containsKey(value)
/**
* 思路:[不常用 容易懵]
* 获取键值对 Set集合
* 遍历键值对
* 获取键
* 获取值
*/
public class Demo2 {
public static void main(String[] args) {
Map<String, String> hashMap = new HashMap<>();
hashMap.put("CN", "中国");
hashMap.put("RU", "俄国");
hashMap.put("UK", "英国");
// entry 条目
// { [key,value] , [key,value] }
Set< Entry<String, String> > entrySet = hashMap.entrySet();
for (Entry<String, String> entry : entrySet) {
// 获取键
String key = entry.getKey();
// 获取值
String value = entry.getValue();
System.out.println(key+" --> "+value);
}
}
}
七、了解HashMap和Hashtable的区别
线程安全问题。
多线程:重要,复杂,难度高。
相同点:
1、HashMap和Hashtable都是Map接口的实现,都可以实现键值对存储。
不同点:
1、HashMap键值存储都可以为null ,如果键为null则只能存储一次
Hashtable键值存储都不允许为null
2、 HashMap是线程不安全的,效率高
Hashtable是线层安全的,效率低。
工具类:
Collections:集合工具类
void sort(集合); // 对集合进行升序排序
int max(集合); // 获取集合中的最大值
int min(集合); // 获取集合中的最小值
int binarySearch (集合,要查找的元素);// 查找指定的键
void shuffle(集合);// 打乱集合元素顺序
Arrays:数组工具类
1.比较两个数组的元素是否完全一致:boolean equals(数组1,数组2)
// 判断两个数组的元素是否全相同
boolean equals = Arrays.equals(arr1, arr2);
System.out.println("两个数组的元素是否都相同:"+equals);
2.将数组的所有元素转换为字符串:String to String(数组)
// 将数组内的所有元素直接展示为字符串
String string = Arrays.toString(arr1);
System.out.println(string);
3.将数组的元素进行升序排序:void sort(数组);
// 升序排序
Arrays.sort(arr1);
System.out.println(Arrays.toString(arr1));
4.将数组的元素全部填充为某个值:void fill(数组,填充的值)
// 把数组元素赋值成某个值
Arrays.fill(arr2, 8);
System.out.println(Arrays.toString(arr2));
5.将数组的元素复制到一个指定长度的新数组中:对应的数组类型:copyOf(老数 组,指定长度)
// 将一个数组复制成一个指定长度的新数组
int[] newArr = Arrays.copyOf(arr1, arr1.length + 1);
System.out.println(Arrays.toString(newArr));
6.二分查找,查找之指定元素在数组中的索引/下标(数组必须已经进行升 序排序):int binarySearch(数组,查找的值)
// 二分查找 (必须升序排序过)
int index = Arrays.binarySearch(arr1, 9);
System.out.println(index);
Arrays.asList(T…t);可以创建集合并且赋值
八、掌握泛型的基本使用
JDK1.5才出现的
包装类、注解、泛型…
泛型集合:
它是用来约束/声明集合元素的数据类型的
1、泛型必须是引用数据类型,如果是存储基本数据类型,则必须将其转换为对应引用数据类型(包装类。)
public class Demo2 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
News news1 = new News(1, "震惊!巴黎圣母院失火!", "李天一");
News news2 = new News(2, "震惊!LOL玩家和DOTA玩家竟然在众人面前互斥对方算什么男人!", "史浩然");
News news3 = new News(3, "是中国人必须转!不转不是中国人!", "范国强");
list.add(news1);
list.add(news2);
list.add(news3);
// 没有泛型必须使用强转 不安全
for (Object object : list) {
if(object instanceof News) {
News news = (News)object;
System.out.println(news.getAuthor());
}
}
}
}
推荐使用
主要用于约束集合中存储的元素的数据类型,减少数据类型转换的代码,减少数据类型转换失败的异常发生。
// 写法:
public class Dema{
public static void main(String[] aegs){
// <String> 约定数据类型
List<String> list = new ArrayList<String>();
list.add("zhangsan");
list.add("李四");
// 但注意了,在上边,已经约到了数据类型,那么非约到数据类型的写入会报错。例如:
list.add(55);// 数据类型不匹配 报错
for(String elm : list){
System.out.println(elm);
}
}
}
2、利用泛型将程序变得更加易扩展(通过泛型占位符来进行扩展
javaxxxxxxxxxx public class Test<T> {
private String field1;
private String field2;
// 不确定是什么类型的
private T field3;
}
List<T> Arrays.asList(T... a);