第七章:集合

1.集合概念(java.util包)

1.集合 数组 ---->容器 存储一组数据

2.数组就是容器:同一类型,创建时指定容量,长度不变,在内存空间连续存储

3.不足:长度固定,不能改变

需求:程序运行时数据数量随时会发生改变,存储结构也会有特殊需求(增删多---链表结构;查询多---数组结构)-----为什么java提供那么多(不同类型)集合类?

2.集合API

集合就是容器 操作: 增删改查

1.集合体系:(单列集合Collection和双列集合Map)

Java的集合框架是由很多接口、抽象类、具体类组成的,都位于java.util包中

 

集合类有单列结构 双列结构,单列都继承Collection 双列继承Map接口(键 值 对)

3.Collection接口

1.Colletion接口常用方法:(单列集合共有的方法)

Collection<E> 集合类默认使用泛型,如果不写默认Object

java集合类默认使用泛型,如果没有定义存储的数据类型,默认Object

add() 增加元素 addAll可以把另一个集合加进去

clear () 清空列表

contains()是否包含指定元素

c.retainAll(c1) c只保留与c1中共有的部分 保留交集 c1不变返回ture (如果两个集合一样 不变 返回false 两集合不变)

isEmpty() 是否为空

remove() 删除指定第一个元素 成功返回true 否则false

c.removeAll (c1) 删除c中c1有的内容 不是c1 c1不变

size() 实际往里面放的元素个数 长度

toArry();返回一个含此类集合所有元素的数组(即把集合以数组的形式返回)但是是Object类型的数组

想要指定类型的话:如String[] a=原来集合名称.toArray(new String[长度 原来集合名称.size]);这样得到的就是String类型的数组

输出:System.out.println(Arrays.toString(数组名));

import java.util.ArrayList;
import java.util.Collection;
​
public class Jihe {
    public static void main(String[] args) {
        Collection<String> c=new ArrayList<String>();// 泛型  上升到父类 向上转型  (最好统一类型 指定存储类型  就不会出现转型问题)
        c.add("a");//
        c.add("b");
        //c.add(1);//自动包装Integer
//c.clear();
        System.out.println(c);
        System.out.println(c.contains("s"));
        System.out.println(c.isEmpty());
        System.out.println(c.remove("a"));
        System.out.println(c.size());
    }
​
}

2.为什么要用泛型?**

泛型 参数化类型 把数据类型当做形参传进去

安全问题:不明确类型会默认Object 装的时候爽了 一顿乱装 但存在向下转型问题 可以通过泛型在创建对象时把类型当做参数传进去 存一样的 <引用类型> 必须是引用类型 就是把类型固定

// public class<T>{ } T是任意标识符 由外部指定 可以是T V K E

3.List接口及实现类

ArraysList--->数组: 连续空间 查询快 从中间添加删除效率低

LinkedList--->链表: 查询慢(从头或尾节点查)插入删除效率高

Vector--->数组:线程安全

4.ArraysList常用方法:

·构造方法:

ArraysList<String> alist=new ArraysList();

4.List 接口及实现类

为什么介绍那么多类?

这些类都是已经有的 有很多方法功能 我们根据自己的需求选出适合的类 创建个对象就可以使用其方法

List接口有三个实现类 ArrayList LinkedList Vetor

1.数组结构ArrayList:查询快 增删慢 连续空间

2.链表结构LinkedList: 不需要连续空间 查询慢 但中间增删快(指针移动)

3.Vetor

4.详细:

一、ArrayList

1.ArrayList<String> alist=new ArrayList<>( 这里可以指定长度 也可以默认10);//创建一个长度为10的底层数组 但在添加第一个元素的时候才算真正创建

  1. Collection共有的方法他都有 还有特有的 因为数组结构可以索引 所以add(位置,“要插入的数据”)获取和删除元素也可以通过位置索引

  2. add()添加元素到集合中的过程:

    先检查底层数组能不能放下,可以就添加到末尾,不可以就会扩容

    if(newCapacity-elementDate.length>0)

    grow(minCapacity)//扩容 扩容为原来1.5倍(数组复制 创建一个新数组 加进去 把原来的数组覆盖)

    有扩容机制就要想到size()方法 考虑到数组长度和实际长度可能不等 size()表实际长度

    4.removeRange()是受保护的 子类访问父类中受保护的方法(继承ArrayList)

    5.比较器sort(传过来个接口)

    alist.sort(new Compare<String>){

    @Override

    public int cocmpare(String o1,String o2){

    return 0;//一次性的 就这样写

    }

    });

    比较器再简化 函数式编程代替匿名内部类写法(把函数当参数丢进去):

    alist.sort((String o1,String o2)->{return o1.compareTo(o2);})

    二、LinkedList(具体后面讲)

1、链表集合(栈 队链用到)

2、可存储重复元素 add()每添加一个元素创建一个Node对象(它里面有E item,Node<E> next,Node<E> prev)

为什么查询慢?geet()方法 不是从前面就是从后面开始找

三、Vector(数组实现)(线程安全 有synchronzed 锁)

5.List接口集合迭代

1.for循环:

for(int i=0;i<alist.size();i++){//能用size尽量用size 没有再用length

System.out.println(alist.get(i));

}

2.增强for:

for(String s:alist){

System.out.println(s);

}

3.迭代器(可以从头 也可以从尾)

 

Iterator<String> it=alist.iterator();

whlie(it.hasNext()){

String s=it.next();//如果有拿到下一个元素

System.out.println(s);

}

特殊的迭代器 使用范围更小 功能更强大:

从前向后找:

 

从后向前找:

 

但只能用在List集合

4.他们的区别:

·for循环支持在遍历过程中删除集合中的元素 注意元素前移,i++ 不然会漏掉一些元素

·增强for循环不支持遍历的时候删除元素

·迭代器

 

6.Set 接口

Set接口继承了Collection接口

不重复 没有索引

一.Set接口两个实现类:

1.HashSet:无序

1.底层数据结构:哈希表+链表

2.TreeSet:有序

1.底层数据结构:二叉树(红黑树是一种自平衡的二叉树)

2.add 不能加重复元素

3.遍历:没有索引 只能说增强for循环 或者iterator迭代器

7.Set 接口集合迭代

没有索引 只能说增强for循环 或者iterator迭代器

8.Map 接口 (双列)

Map接口常用方法:

加:put ("键","值") 如果有相同的key 会用该对于的值把上一个key对于的值替代掉

删:remove("键") 以键删值

取:get("键") 以键找值

containsKey("键") 有没有这个键 返回ture / false

containsValue("值") 有没有这个值

1.HashMap hash表(数组)+链表+红黑树 线程不安全

1.键 值 对 存储(键不能重复 值可以 键值一一对应)

2.put过程

添加一个元素是,会创建一个长度为16的哈希表(数组),哈希值取余16 计算出它的位置,如果要添加的位置有元素,就会生产一个链表,当链表的长度等于8(太长效率就会降低),就会将链表自动转换为红黑树,当数组内容站到12个位置(3/4)就会对数组扩容(为原来的2倍)

位置=(n-1)&hash 就相当于=哈希值取余16

无重复:重复的值不是加不进去,而是加进去替换原来的值

 

当向HashMap中添加元素时,先用key计算出一个哈希值,通过哈希算法,计算出此key在哈希表中的位置,如果这个位置上没有元素,直接插入

当再次插入值时,如果计算出的位置上已经有值存在了,那么就会向元素的下一位添加链表,当链表长度等于8时,将链表转为红黑树,当数组被使用4分之3时就扩容为原来2倍(2的倍数 扩容的复制方便)

扩容:用一定的空间换查询的时间

当数的结点个数删为6 转为链表

2.TreeMap 红黑树实现

1.key的类型必须实现Comparable接口,(key)可以按照自然循序排序 重复的也是覆盖掉

3.HashTable hash表+链表+红黑树 线程安全

实现了同步 线程安全

HashTable不能存储为null的键 HashMap可以

9.Map接口集合迭代

1.增强for循环:(不提倡)(拿出所有的key 对key进行遍历)

如:

Set<String> keyset=map.keySet();//拿到key

for(String key:keyset){

System.out.println(key+":"+map.get(key));

}

map迭代器:

 

把map里面所有key值都放到keyset里面去 得到一个Set集合 对Set进行遍历 就可以用增强for循环遍历

 

通过key找到对应的值

2.(提倡)专门为Map遍历提供的

Map底层为了方便遍历,将键值对存入一个Entry对象中,将多个Entry对象放到Set集合中

Set<Entry<String,String>> entrySet=map.entrySet();

for(Entry<String,String> entry:entrySet){

System.out.println(entry.getKey()+":"+entry.getValue());

}

 

把每一个键值对封装到一个叫Entry的对象里 并把多个Entry对象放到Set集合里

 

entry. 就可以直接拿到 键和值 想拿哪个拿哪个

10.Collections类

Collections类: 是集合处理的工具类,里面包含的都是静态方法类似Arrays类

Collection.addAll(c.elements);

test(1,2,3,4,5);//就可以放进去

public static void test(int...c也可以这样写int a,int b,int...c就a对应1,b对应2,c对应3,4,5){

System.out.println(Arrays.toString(c));

}

int...c 可变长度的参数,本质是数组

一个参数列表只能有一个可变长度的参数,并且只能放在参数列表的最后一位

 

意思是实现Collection的都可以传 就上面所说的集合类

 

加入比较器:

升序:

 

降序:

 

更简化的函数表达:(只能有一个抽象方法 不然不知道o1 o2是啥)

 

swap():集合中交换两个元素的位置

 

copy()复制:小的复制到大的(用到的是size 不是length)

 

emptyList()空列表:返回空集合new EmptyList<>() 不能使用 只是为了满足语法上的判断需要(具体我也不理解)

 

填充:

 

最大值:

 

替换:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

团团kobebryant

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值