一 关于集合框架
1 集合是Java提出的用来进行多个数据存储的"容器",数组也具备这样的功能,
2 由于数组一旦创建长度固定,且只能存放一种数据类型,不够灵活,Java提出更灵活,存放任意的数据类型的容器也就是集合
3 集合和数组的异同点
相同点:都是用来存储多个数据类型的容器
不同点:存储的灵活性
① 长度: 数组一旦创建长度固定;集合可以灵活存储
② 数据类型: 数据可存放指定的一种数据类型,既可以是基本数据类型也可以是引用数据类型;集合只能存放任意的引用数据类型(如果赋值基本数据类型,底层以基本数据类型的包装类存储,自动装箱的形式完成)
二 集合框架的分类
1 单列集合-将数据进行一个一个的存储
2 双列集合-基于 Key 与 Value 的结构存储数据
3 单列集合存储特点以及具体实现类底层存储
① 存储特点
Collection接口: 既可以存储重复值,也可以存储不重复值;既可以有序,也可以无序
List接口: 有序不唯一
Set接口: 无序且唯一
Queue接口: 先进先出 队列式存储
② 实现类底层存储模式
ArrayList类: 底层基于动态数组存储
LinkedList类: 底层基于双链表存储
TreeSet类: 底层基于二叉树存储
HashSet: 底层基于哈希码值存储
三 单列集合
1 ArrayList类
// 可调整大小的数组的实现List接口
Class ArrayList<E>
< E> – 表示泛型
① 泛型的含义: 泛指的任意的引用数据类型
② 泛型使用的格式: <字母> – 字母一般是任意一个,必须得大写
java中规定的泛型字母 | 含义 |
---|---|
E | Element,表示集合中存储元素的类型 |
K | KEY,表示Map中键的类型 |
V | VALUE,表示Map集合中值的类型 |
R | Result,表示方法的返回值类型 |
? | 表示不确定的任意一种类型 |
T | Type,存储的类型 |
③ 使用泛型的好处:提高集合存储数据的安全性;一旦集合使用泛型,等效于数组;实际开发中,一般在集合使用的时候,必须配合泛型使用
2 创建集合
ArrayList对象有初始值;长度是10;可以进行扩容;扩容的倍数是1.5
public class ArrayListTest {
public static void main(String[] args) {
ArrayList list=new ArrayList();
// 直接打印集合对象,显示集合中所有元素
System.err.println(list);
}
}
3 增加元素
// 在集合的尾部追加指定的元素
public boolean add(E e)
// 将指定的元素插入到集合的指定位置上
public void add(int index ,E e)
// 例子
public class ArrayListTest {
public static void main(String[] args) {
ArrayList<Object> list=new ArrayList<Object>();
list.add("qq");
list.add(13);
list.add(false);
list.add('@');
// 指定下标添加元素
list.add(2,5);
list.add("qq");
list.add(0,23);
System.err.println(list);
//[23, qq, 13, 5, false, @, qq]
}
}
4 删除元素
// 清空集合中所有数据,但是保留集合结构
public void clear()
// 移除指定位置上的元素,并且返回该元素
public E remove(int index)
// 将指定元素从集合中移除(如果存在)
public boolean remove(E e)
// 例子
public class ArrayListTest {
public static void main(String[] args) {
ArrayList<Object> list=new ArrayList<Object>();
list.add("qq");
list.add(13);
list.add(false);
list.add('@');
// 指定下标添加元素
list.add(2,5);
list.add("qq");
list.add(0,23);
System.err.println(list);
// [23, qq, 13, 5, false, @, qq]
// 删除指定元素时若元素类型是整数或字符型,需将值传递为元素对象进行删除
// 因为可能会将传递的值认为是下标,造成数组下标越界
// 值转对象:类型强转 (包装类)值
System.err.println("移除元素5"+list.remove((Integer)5));
// 移除元素5true
System.err.println(list);
// [23, qq, 13, false, @, qq] 删除成功返回 true
System.out.println("移除位置3上的元素:"+list.remove(3));
// 移除位置3上的元素:false(返回元素本身)
System.out.println(list);
list.clear();
System.out.println("清空后的list"+list);
}
}
5 修改元素
// 使用指定的元素修改指定位置上的原有元素,将原有的元素返回
public E set(int index,E e )
// 例子
public class ArrayListTest {
public static void main(String[] args) {
ArrayList<Object> list=new ArrayList<Object>();
list.add("qq");
list.add(13);
list.add(false);
list.add('@');
// 指定下标添加元素
list.add(2,5);
list.add("qq");
list.add(0,23);
System.err.println(list);
// [23, qq, 13, 5, false, @, qq]
System.out.println("用!替换1位置上的元素"+list.set(1,"!"));
// 返回指定位置上的元素 用!替换1位置上的元素qq
System.out.println("替换后"+list);
// 替换后[23, !, 13, 5, false, @, qq]
}
}
6 查询元素
// 获取集合指定位置上的元素
public E get(int index)
// 获取指定元素在集合中第一次出现的位置,如果不存在返回-1
public int indexOf(E e)
// 获取指定元素在集合中最后一次出现的位置,如果不存在返回-1
public int lastIndexOf(E e)
// 获取集合元素的真实个数
public int size()
// 获取集合中指定范围内的所有元素,不包含结束位置
public List<E> subList(int beginIndex,int endIndex)
// 例子
public class ArrayListTest {
public static void main(String[] args) {
ArrayList<Object> list=new ArrayList<Object>();
list.add("qq");
list.add(13);
list.add(false);
list.add('@');
// 指定下标添加元素
list.add(2,5);
list.add("qq");
list.add(0,23);
System.err.println(list);
// [23, qq, 13, 5, false, @, qq]
System.out.println("集合长度"+list.size());
// 集合长度7
System.out.println("2位置上的元素"+list.get(2));
// 2位置上的元素13
System.out.println("qq第一次出现的位置"+list.indexOf("qq"));
// qq第一次出现的位置1
System.out.println("qq最后一次出现的位置"+list.lastIndexOf("qq"));
// qq最后一次出现的位置6
System.out.println("[1,3)范围内的元素"+list.subList(1,3));
// [1,3)范围内的元素[qq, 13]
}
}
7 判别元素
// 判断指定的元素是否是集合中的元素
public boolean contains(E e)
// 例子
public class ArrayListTest {
public static void main(String[] args) {
ArrayList<Object> list=new ArrayList<Object>();
list.add("qq");
list.add(13);
list.add(false);
list.add('@');
// 指定下标添加元素
list.add(2,5);
list.add("qq");
list.add(0,23);
System.err.println(list);
// [23, qq, 13, 5, false, @, qq]
System.out.println("@在集合中吗"+list.contains('@'));
// @在集合中吗true
}
}
8 Collections类 – 操作所有单列集合工厂类
// 获取指定单列集合中元素的最大值
public static E max(Collection<E> c)
// 获取指定单列集合中元素的最小值
public static E min(Collection<E> c)
// 给指定的List集合进行默认的升序排序
public static void sort(List<E> list)
// 将指定的多个散数据(引用数据类型),同时存放到List 集合中,Arrays类提供
public static List<T> asList( T ..... t)
// 例子
public class ArrayListTest {
public static void main(String[] args) {
ArrayList<Integer> list=new ArrayList<Integer>();
list.add(13);
list.add(7);
list.add(45);
list.add(2);
list.add(2,5);
list.add(0,23);
System.err.println(list);
// [23, 13, 7, 5, 45, 2]
Collections.sort(list);
System.out.println("排序后"+list);
// 排序后[2, 5, 7, 13, 23, 45]
System.out.println("最大"+Collections.max(list));
System.out.println("最小"+Collections.min(list));
// 最大45 最小2
}
}
// 将任意的多个引用数据类型同时存储在List集合中
public class ArrayListTest {
public static void main(String[] args) {
List<Object> list = Arrays.asList("qwer", 'e', 456, Math.PI, true);
System.err.println(list);
// [qwer, e, 456, 3.141592653589793, true]
// list是接口对象,因此不能直接调用接口中的抽象方法完成操作
// 需将list集合的数据放到ArrayList中,通过ArrayList对象调用方法完成操作
ArrayList<Object> als=new ArrayList<Object>();
for (Object o: list) {
als.add(o);
}
als.add("asdwd");
System.out.println(als);
// [qwer, e, 456, 3.141592653589793, true, asdwd]
}
}
9 LinkedList类 – 创建集合
// 双向链表
Class LinkedList<E>
// 创建集合
public LinkedList()
10 LinkedList 与 ArrayList 集合中的一致方法,使用效果也一致,参考ArrayList同名方法
11 增加元素
// 将指定的元素插入到链表的头部
public void addFirst(E e)
//将指定的元素查入到链表的尾部
public void addLast(E e)
// 例子
public class ArrayListTest {
public static void main(String[] args) {
LinkedList<Integer> ll=new LinkedList<>();
ll.add(12);
ll.add(122);
ll.add(142);
ll.add(2,22);
System.err.println(ll);
// [12, 122, 22, 142]
ll.addFirst(-11);
ll.addLast(-22);
System.err.println(ll);
// [-11, 12, 122, 22, 142, -22]
}
}
12 删除元素
// 移除链表中头部位置上的元素
public E removeFirst()
// 移除链表中尾部位置上的元素
public E removeLast()
// 例子
public class ArrayListTest {
public static void main(String[] args) {
LinkedList<Integer> ll=new LinkedList<>();
ll.add(12);
ll.add(122);
ll.add(142);
ll.add(2,22);
System.err.println(ll);
// [12, 122, 22, 142]
ll.removeFirst();
System.err.println(ll);
// [122, 22, 142]
}
}
四 java的数据存储方式
1 数据存储方式:实质上就是集合型数据在jvm虚拟机中存取的操作
2 分类
① 队列式存储: 先进先出,类似于吸管
存: LinkedList类 – addFirst()
取: LinkedList类 – removeLast()
② 堆栈式存储 : 先进后出
存:LinkedList类中 – addFirst()
取:LinkedList类中 – removeFirst()
代码演示 – 堆栈内存存储方式
public class PriStack<T> {
// 定义私有化变量LinkedList
private LinkedList<T> ll;
// 定义当前类有参构造器,参数是用户传递的LinkedList对象
public PriStack(LinkedList<T> ll){
this.ll=ll;
}
// 存数据
public void save(T t){
ll.addFirst(t);
}
// 取数据
public T gain(){
return ll.removeFirst();
}
// 显示集合元素
public void show(){
System.err.println(ll);
}
// 取元素个数
public int size(){
return ll.size();
}
}
public class PriStackTest {
public static void main(String[] args) {
PriStack<String> ps=new PriStack<String>(new LinkedList<String>());
ps.save("this a");
ps.save("this b");
ps.save("this c");
ps.show();
// [this c, this b, this a]
while (ps.size()>0){
System.out.println(ps.gain());
}
//this c
//this b
//this a
}
}
3 泛型的应用
① 泛型可以使用的位置 : 类 和 类成员 (一般成员方法)
② 泛型使用的前提: 定义的类或类成员完成对数据的存取操作时
五 HashSet类
1 创建对象
// 此类实现Set接口
public class HashSet<E>
// 创建对象
public HashSet()
2 Set集合是无序的散列表,元素的位置相对不稳定,故Set集合中摒弃List集合中所有有关位置的方法,没有关于位置操作的方法;其余与List同名方法参照List集使用
public class play {
public static void main(String[] args) {
HashSet<Object> hs=new HashSet<>();
hs.add("132");
hs.add(213);
hs.add('*');
hs.add("dw");
hs.add(5.5);
System.out.println(hs);
// [132, dw, 213, 5.5, *]
}
}
3 例子
// 向集合存放十个数,以升序排序的方式显示,同时显示最大最小值
public class play {
public static void main(String[] args) {
ArrayList<Integer> list=new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
// 注意优先级问题
list.add((int)(Math.random()*100));
}
System.err.println("排序前"+list);
Collections.sort(list);
System.err.println("排序后"+list);
System.err.println(Collections.max(list));
System.err.println(Collections.min(list));
}
}
// 方式二
public class play {
public static void main(String[] args) {
HashSet<Integer> hashSet=new HashSet<Integer>();
while (hashSet.size()<10){
hashSet.add((int) (Math.random()*100));
}
System.err.println(hashSet);
System.err.println(Collections.max(hashSet));
System.err.println(Collections.min(hashSet));
}
}
六 迭代器
1 迭代表示产品的更新换代,在集合中所谓的迭代就是操作(存和取)指定集合中的元素
2 数组对于元素的存取操作的方式
① 存
for(int i=0;i<数组名.length;i++){
数组名[i]=值;
}
② 取
//当需要操作元素下标的时候 -- 使用普通for循环
for(int 1=0; i<数组名.length;i++){
变量=数组名[i];
}
//当需要直接操作数组元素的时候 -- 使用增强for (forEach)
for(数据类型 变量名 : 数组名){
操作变量;
}
3 对于List集合-单列集合元素存取操作
① 存数据 – 普通for循环
for(int i = 0; i<数值;i++){
集合对象名.add(E e);
}
//推荐使用while原因集合长度不限,因此很少指定长度
while(true){
集合对象名.add(E e);
if(判断条件){
break;
}
}
② 取数据
//方式一:根据元素下标获取元素 普通for
for(int i= 0 ;i<集合对象名.size();i++){
对象=集合对象名.get(i);
}
//方式二:直接操作元素 增强for
for(类 对象 : 集合名){
操作对象;
}
//方式三: 迭代器,java封装好的一个接口Iterator迭代接口
Iterator<集合泛型的类型> it = 集合对象名.iterator();//获取迭代器对象
while(it.hasNext()){//判断下一个位置是还有元素
对象=it.next();//获取集合中的元素
}
4 Set集合中对元素的存和取操作
① 存数据
//由于Set集合没有位置,因此只能使用while循环添加数据
while(true){
集合对象名.add(E e);
if(判断条件){
break;
}
}
② 取数据
for(类 对象: 集合名){
操作对象;
}
5 关于迭代器(单列)
hasNext方法的详解 – 游标指针操作原理
通过集合对象获取迭代器对象,通过迭代器对象调用hasNext(),此时游标指针创建,默认停放的位置是-1,表示没有获取到元素;通过while循环启动游标指针,在指定的单列集合中移动
在迭代器中对该方法限定移动范围[0,集合对象名.size())
例子
// 迭代器只操作单列集合
public class play {
public static void main(String[] args) {
HashSet<Integer> hashSet=new HashSet<Integer>();
while (hashSet.size()<10){
hashSet.add((int) (Math.random()*100));
}
System.err.println(hashSet);
// 通过单列集合对象调用iterator()方法获取迭代器对象,有迭代器对象才能调用迭代器方法
Iterator<Integer> it=hashSet.iterator();
// 通过迭代器对象调用方法,判断集合中下一个位置上是否还有元素,有则继续
while (it.hasNext()){
// 元素存在,通过迭代器对象获取元素赋值给i,显示
Integer i=it.next();
// 显示大于60的元素
if(i>60){
System.err.println(i);
}
}
}
}