当前位置: 首页 > news >正文

集合:Collection详解.

目录: 

一、集合概述
二、集合继承关系图【图重点 要会看源码 背会】
三、Collection接口常用方法
四、关于集合的迭代/遍历【重点】
五、List 和 Set集合存储元素的特点
六、contains方法深刨解析【重点】
七、remove()方法深刨解析
八、关于集合中元素的删除 p518
九、List接口特有方法
十、ArrayList集合初始化容量及扩容
十一:泛型
十二、增强for循环:foreach
十三、演示HashSet集合特点
十四、演示TreeSet集合特点

一、集合概述

1.1、什么是集合?有什么用

数组其实就是一个集合。集合实际上就是一个容器。可以来容纳其它类型的数据。

集合为什么说在开发中使用较多?
集合是一个容器,是一个载体,可以一次容纳多个对象。
在实际开发中,假设连接数据库,数据库当中有10条记录,
那么假设把这10条记录查询出来,在java程序中会将10条
数据封装成10个java对象,然后将10个java对象放到某一个
集合当中,将集合传到前端,然后遍历集合,将一个数据一个
数据展现出来。

1.2、集合中储存什么

集合不能直接存储基本数据类型,另外集合也不能直接存储java对象,
集合当中存储的都是java对象的内存地址。(或者说集合中存储的是引用。)
list.add(100) ; //自动装箱Integer
注意:
集合在java中本身是一个容器,是一个对象。
集合中任何时候存储的都是"引用”。/ 对象内存地址

内存图如下:

二、集合继承关系图【图重点 要会看源码 背会】

在java中集合分为两大类:
一类是单个方式存储元素:
单个方式存储元素,这一类集合中超级父接口: java.util.Collection;

一类是以键值对儿的方式存储元素
以键值对的方式存储元素,这一类集合中超级父接口: java.util.Map;

第一类:Collection 

 

 第二类:Map

总结:所有的实现类

ArrayList:底层是数组
LinkedList:底层是双向链表
Vector:底层是数组,线程安全的,效率较低,使用较少
HashSet:底层是HashMap,放到HashSet集合中的元素等同于放到HashMap集合key
部分了

TreeSet:底层是TreeMap,放到TreeSet集合中的元素等同于放到TreeMap集合key部
分了
HashMap:底层是哈希表
Hashtable:底层也是哈希表,只不过线程安全的,效率较低,使用较少了
Properties:是线程安全的,并且key和value只能存储字符串String
TreeMap:底层是二叉树。TreeMap集合的key可以自动按照大小顺序排序

List集合存储元素的特点:
    有序可重复。
    有序:存进去的顺序和取出的顺序相同,每一个元素都有下标
    可重复:存进去1,可以再存储一个1

Set集合存储元素的特点:。
    无序不可重复。
    无序:存进去的顺序和取出的顺序不一定相同。另外Set集合中元素没有下标
    不可重复:存进去1,不能再存储1了

SortedSet (SortedMap) 集合存储元素特点:。
    首先是无序不可重复的(因为继承了Set集合),但是SortedSet集合中的元素是可排序的
    无序:存进去的顺序和取出的顺序不一定相同。另外Set集合中元素没有下标
    不可重复:存进去1,不能再存储1了
    可排序:可以按照大小顺序排列

三、Collection接口常用方法

1、Collection集合中不能直接储存基本数据类型,也不能储存java对象,只能储存java对象的内存地址(引用)

2、Collection中的常用方法(因为Collection为父类 所以我们研究父类就相当于研究了子类)
    boolean add(E e)   向集合中添加元素
    int size()  获取集合中的元素个数
    boolean remove(Object e)    删除集合中某个元素
    boolean contains(Object e)  判断集合中是否包含指定的元素
    void clear()    清除集合内的元素
    boolean isEmpty()   判断该集合元素是否为0
    Object[] toArray()  调用这个方法把集合转换成数组  [了解即可]

 代码演示如下:

public class CollectionTest01 {public static void main(String[] args) {// 创建一个集合对象// Collection s =new Collection();   // 接口是抽象的,无法实例化// 多态Collection c =new ArrayList();  // ArrayList实现了Collection[非抽象类实现抽象类必须子类必须重写抽象类方法]// 测试Collection接口中的常用方法c.add(100); // 自动装箱 实际上放进去了一个对象的内存地址. Integer x =new Integer(1200); 实际上把引用x放进去了c.add(3.14); // 自动装箱c.add(new Object()); // 自动装箱c.add(new Student()); // 自动装箱// 集合中的元素个数System.out.println("集合中的元素个数:"+c.size());   // 4// 判断集合中是否包含指定的元素// 如集合中是否包含3.14boolean s =c.contains(3.14);    // 自动装箱System.out.println(s);  // true// 从集合中删除指定元素c.remove(3.14);    // 自动装箱System.out.println("删除指定元素后集合中的元素个数:"+c.size());    // 3// 清空集合元素c.clear();System.out.println("清空集合内的元素后集合中的元素个数:"+c.size());  // 0// 判断集合中元素是否为空System.out.println("集合中元素是否为空:"+c.isEmpty());   // true}
}class Student{}

四、关于集合的迭代/遍历【重点】

 代码演示如下:

package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
关于集合迭代/遍历(重点)*/
public class CollectionTest02 {public static void main(String[] args) {// 创建集合对象Collection c =new ArrayList();// 向集合中添加元素c.add(100);c.add(3.14);c.add("hello");c.add(new Object());// 对集合中的元素进行迭代// 第一步:获取集合对象的迭代器对象IteratorIterator i =  c.iterator();// 第二步:通过以上获取的迭代器对象开始迭代/遍历集合// if (i.hasNext()){   // 调用迭代器对象Iterator中的HasNext方法 先判断集合是否还有元素可以迭代//    Object o =i.next(); // 注意:add存进去的是什么类型元素,取出来还是什么类型元素(自动装/拆箱)]//    System.out.println(o); // 只不过输出的时候会转换成字符串,因为这里println会调用toString()方法// }// 改进while (i.hasNext()){System.out.println(i.next());}}
}

输出结果:

五、List 和 Set集合存储元素的特点

List:有序可重复        Set:无序不可重复

List集合对象代码演示如下: 

package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;public class CollectionTest03 {public static void main(String[] args) {// 创建List集合对象// ArrayList集合: 有序可重复// 有序: 存进去的元素顺序和取出来的元素顺序相同// 可重复: 比如存过1元素,还可以存1元素Collection c =new ArrayList(); // (ArrayList实现了List接口 关系看上述图)// 往集合中添加元素c.add(1); // 自动装箱c.add(2);c.add(3);c.add(4);c.add(5);c.add(1);// 对集合中的元素进行迭代Iterator it =c.iterator();  // 迭代器对象while (it.hasNext()){System.out.println(it.next());}}
}

输出结果:

 Set集合对象代码演示如下:

package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;public class CollectionTest03 {public static void main(String[] args) {// 创建Set集合对象// HashSet集合: 无序不可重复// 无序: 存进去的元素顺序和取出来的元素顺序不一定相同// 不可重复: 比如存过1元素,不可以再存1元素,再存1的话也拿不出来Collection c =new HashSet(); // (HashSet实现了Set接口 关系看上述图)// 往集合中添加元素c.add(1); // 自动装箱c.add(2);c.add(3);c.add(4);c.add(5);c.add(1);   // 拿不出来了 重复// 对集合中的元素进行迭代Iterator it =c.iterator();  // 迭代器对象while (it.hasNext()){System.out.println(it.next());}}
}

输出结果:

 六、contains方法深刨解析【重点】

总结: contains方法是用来判断集合中是否包含某个元素的方法,
        那么它在底层是怎么判断集合中是否包含某个元素的呢?
                调用了equals方法进行比对。(String类重新了父类equals()方法、equals比较的是对象的中内容)

!!!!!以后放入集合中对象级别的元素时比如User类,记得一定要重写equals()方法

代码演示如下: 

package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;public class CollectionTest04 {public static void main(String[] args) {// 创建一个集合对象Collection c =new ArrayList();// 向集合中添加元素String s1 =new String("junker");c.add(s1);String s2 =new String("jun");c.add(s2);String s3 = new String("Dog");c.add(s3);System.out.println("集合中元素的个数:"+c.size());// 判断c集合中是否包含s4String s4 =new String("jun");boolean s =c.contains(s4);    // 虽然集合中存放的是对象的内存地址,但是contains底层调用了equals()方法,String类当中重写了父类Object的equals()方法所以比较的还是对象内容//注意:父类Object的equals()方法其实比较的还是内存地址,需要我们重写之后才能判断对象内容System.out.println(s);  // true    /*总结: contains方法是用来判断集合中是否包含某个元素的方法,那么它在底层是怎么判断集合中是否包含某个元素的呢?调用了equals方法进行比对。(String类重新了父类equals()方法、equals比较的是对象的中内容)*/}
}

eg:当存放到集合里面的元素不是String类型的时候:contains比较是否有该元素的时候,记得重写equals方法

代码演示如下:

package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;public class CollectionTest05 {public static void main(String[] args) {// 创建集合对象Collection c =new ArrayList();//向集合中添加元素c.add(new User("jun"));c.add("junker");User user =new User("jun");// 判断集合当中是否存在了user对象元素// User类当中没有重写equals()方法时:// System.out.println(c.contains(user));   // false// 结论;false的原因是contains()方法底层调用了equals()方法进行比较两个对象的内容是否相同的,// 但是User类没有重写父类Object的equals()方法,而父类当中的equals是用“==”判断两个对象的,“==”判断的是两个对象的内存地址,// 因此要判断集合当中两个对象的内容是否重复了 需要对User重写父类的equals()方法 进而比较两个对象的name// 重写父类的equals()方法后:(比较对象中的内容“jun”)System.out.println(c.contains(user));   // true}
}class User{private String name;public User(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}// 重写父类Object的equals()方法@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;User user = (User) o;return this.name == user.name;}
}

七、remove()方法深刨解析

remove()方法底层调用的也是equals()方法 因此我们以后往集合里面存放元素的时候一定要重写equals()方法

代码演示如下: 

package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;public class CollectionTest05 {public static void main(String[] args) {// 创建集合对象Collection c =new ArrayList();//向集合中添加元素c.add(new User("jun"));User user =new User("jun");c.remove(user); // 当删除user的时候,remove底层调用equals()方法 认为“jun”这两个对象是相同的 所以把集合中的删掉了System.out.println(c.size());   // 0}
}class User{private String name;public User(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}// 重写父类Object的equals()方法@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;User user = (User) o;return this.name == user.name;}
}

八、关于集合中元素的删除 p518

代码演示如下:

package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*重点: 当集合的结构发生改变时,迭代器必须重新获取,如果还是用以前的老的迭代器对象 那么会出现异常:ConcurrentModificationException重点: 在迭代集合元素的过程中,不能调用集合对象的remove方法删除元素*/public class CollectionTest06 {public static void main(String[] args) {// 创建集合对象Collection c =new ArrayList();// 向集合中添加元素(集合的结构)c.add("adf");c.add("qwe");c.add("zxc");c.add("ghj");// 获取迭代器对象Iterator it =c.iterator();// 此时迭代器相当于一个快照 已经把上面集合的结构闪拍下来了while (it.hasNext()){Object o =it.next();// c.remove("adf");   //异常 此处不可以使用集合c.remove()的方法删除元素, 因为迭代器已经把上面当时的结构闪拍下来了,不能对其修改了 想要修改还需要再次获取迭代器对象// 但可以通过迭代器对象进行删除元素it.remove();System.out.println(o);}System.out.println(c.size());    // 0}
}

输出结果如下:

九、List接口特有方法【重点】

测试ist接口中常用方法
    1、List集合存储元素特点:有序可重复
    有序:List集合中的元素有下标。
    从0开始,以1递增。
    可重复:存储-个1 ,还可以再存储1.

    2、List既然是Collection接口的子接口,那么肯定List接口有自己“特有”的方法:
        一下只列出List接口特有的常用的方法:
        void add(int index,E element)
        E get(int index)
        int indexOf(Object o)
        int lastIndexOf(Object o)
        E remove(int index)
        E set(int index,E element)  // E为Object

代码演示如下: 

package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class CollectionTest07 {public static void main(String[] args) {// 创建List类型的集合List l =new ArrayList();// 添加元素l.add("A"); // List接口继承Collection接口,所以继承了Collection中的方法l.add("B");// 1、List接口当中独有的方法  void add(int index,E element)l.add(1,"hello");// 由结果可知: 在列表的指定位置插入指定元素(第一个元素是下标)// 这个方法使用不多,因为对于ArrayTest集合来说效率比较低(因为ArrayTest底层是数组,当在数组中插入一个元素后,后面的数组元素需要自动排序)// 迭代Iterator it =l.iterator();while (it.hasNext()){System.out.println(it.next());}// 2、E get(int index)   根据下标获取元素System.out.println(l.get(0));   // A    集合中0下标中的元素// 因为有下标 所以List集合有自己比较特殊的遍历方式// 通过下标遍历[List集合特有的方式,Set没有]System.out.println("====== List独有的遍历方式======");for (int i=0;i<l.size();i++){System.out.println(l.get(i));}System.out.println("==============================");// 3、int indexOf(Object o)// 获取指定对象第一次出现处的索引System.out.println(l.indexOf("B")); // 2// 4、E remove(int index)// 删除指定下标位置的元素// 删除下标为0的元素l.remove(2);System.out.println(l.size());   // 2// 5、 E set(int index,E element) // E为Object// 修改指定位置的元素l.set(0,"world");for (int i=0;i<l.size();i++){System.out.println(l.get(i));}}
}

输出结果:

 十、ArrayList集合初始化容量及扩容

ArrayList集合:
    1、默认初始化容量10(底层先创建一个长度为0的数组,当添加第一个元素的时候,初始化容量为10)
    2、集合底层是一个Object[]数组
    3、构造方法
    new ArrayList();    默认初始化容量10
    new ArrayList(20);  手动初始化容量20
    4、ArrayList集合的扩容:
        原容量的1.5倍
     ArrayList集合底层是数组,怎么优化?
        尽可能少的扩容,因为数组扩容效率比较低,建议使用ArrayList集合的时候
        预估计元素的个数,给定一个初始化容量【扩容前面StringBuffer讲过,扩容是把第一个满元素的数组放到一个更大的数组当中,所以还要放效率会低】

public class CollectionTest08 {public static void main(String[] args) {// 默认初始化容量是10// 数组的长度是10List l =new ArrayList();// 指定初始化容量// 数组的长度是20List list =new ArrayList(20);}
}

ArrayList集合另外一个构造方法

代码演示如下:

package com.bjpowernode.javase.collection;
import java.util.*;public class CollectionTest09{public static void main(String[] args) {// 初始化容量10List l =new ArrayList();// 指定初始化容量100List l1 =new ArrayList(100);// 创建一个HashSet集合Collection c =new HashSet();// 向HashSet集合中添加元素c.add(1);c.add(2);c.add(3);c.add(4);c.add(5);// 通过构造方法就可以把HashSet集合转换成ArrayList集合List list =new ArrayList(c);    List接口特有的迭代/循环元素方法for (int i=0;i<list.size();i++){System.out.println(list.get(i));}
}
}

十一:泛型

1、JDK5. 0之后推出的新特性:泛型
2、泛型这种语法机制,只在程序编译阶段起作用,只是给编译器参考的。 (运行阶段泛型没用! ) 
3、使用了泛型好处是什么?
第一:集合中存储的元素类型统一了。
第二:从集合中取出的元素类型是泛型指定的类型,不需要进行大量的“向下转型”!

4、泛型的缺点是什么?
导致集合中存储的元素缺乏多样性!
大多数业务中,集合中元素的类型还是统一的。 所以这种泛型特性被大家所认可。

没使用泛型之前的代码如下: 

package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class GenericTest01 {public static void main(String[] args) {// 创建一个List集合对象List list =new ArrayList();// 创建元素对象Animal a =new Dog();    // 多态Animal b =new Cat();// 向集合中添加元素list.add(a);list.add(b);// 迭代集合Iterator it =list.iterator();while (it.hasNext()){   // HasNext() 判断集合中是否还有元素了Object obj =it.next(); // 拿到元素// obj.move();  // 无法调用move()方法 因为Object类当中没有move()方法   想要调用move()方法 那么我们需要向下转型if (obj instanceof Animal){ // 也可以obj instanceof Dog 指向特定的对象    obj能指向Animal是因为Animal继承了Object类Animal animal =(Animal)obj;animal.move();}}}
}class Animal{public void move(){System.out.println("animal can move~");}
}class Dog extends Animal{// Dog特有的方法public void eat(){System.out.println("Dog 真可爱~");}
}class Cat extends Animal{// Cat特有的方法public void CatchMouse(){System.out.println("Cat 真棒~");}
}

输出结果:

 当使用泛型之后代码如下:

package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class GenericTest01 {public static void main(String[] args) {// 创建一个List集合对象// 使用泛型List<Animal>之后,表示List集合中只允许存储Animal类型的数据List<Animal> list =new ArrayList<Animal>();    
//JDK8后new ArrayList<Animal> 中的Animal能省略,引入了自动类型推断机制(又称为:钻石表达式)// 创建元素对象(只能存放Animal类型的数据)Animal a =new Dog();    // 多态Animal b =new Cat();// 向集合中添加元素list.add(a);list.add(b);// 储存其他类型数据的话会报错// list.add("9");// 迭代集合// 这个表示迭代器迭代的是Animal类型Iterator<Animal> it =list.iterator();while (it.hasNext()){   // HasNext() 判断集合中是否还有元素了Animal animal =it.next(); // 拿到元素(Animal类型不再是Object类型)// 所以此处不再运行转型就可以拿到子类继承的方法了animal.move();/*但是要想拿到子类特有的方法 还是需要向下转型if (animal instanceof Dog){Dog dog =(Dog)animal;dog.eat();}*/}}
}class Animal{public void move(){System.out.println("animal can move~");}
}class Dog extends Animal{// Dog特有的方法public void eat(){System.out.println("Dog 真可爱~");}
}class Cat extends Animal{// Cat特有的方法public void CatchMouse(){System.out.println("Cat 真棒~");}
}

输出结果:

 十二、增强for循环:foreach

foreach有一个缺点:没有下标,在需要使用下标的循环中,不建议使用增强for循环

对数组使用foreach代码演示如下: 

package com.bjpowernode.javase.collection;public class ForEachTest01 {public static void main(String[] args) {// 创建一个一维数组int [] arr ={1,2,3,4,5};// for循环遍历(普通for)for (int i=0;i<arr.length;i++){System.out.println(arr[i]);}System.out.println("=================================");// 增强for (foreach)// 以下是语法/*for(元素类型 变量名 : 数组或集合){      //变量名就是数组或集合中的元素sout(变量名);}*/// foreach有一个缺点:没有下标,在需要使用下标的循环中,不建议使用增强for循环for (int data:arr){     // data就是数组中的元素(数组中的每一个元素)System.out.println(data);}}
}

输出结果:

 对集合使用foreach代码演示如下:

package com.bjpowernode.javase.collection;import java.util.*;public class ForEachTest02 {public static void main(String[] args) {// 创建List集合List<String> list =new ArrayList<>();   // 使用泛型方式// 向集合中添加元素(因为使用了泛型,所以只能存放String类型数据)list.add("hello");list.add("world");// 遍历 :第一种使用迭代器方式Iterator<String> it =list.iterator();   // 对String类型数据进行遍历while (it.hasNext()){String s =it.next();    // 因为使用了泛型对String类型迭代,所以此处返回的不再是Object类型System.out.println(s);}// 遍历:第二种for循环遍历(因为List集合有一个调用下标可以拿到元素的方法,因此可以for循环) 独有的for (int i=0;i<list.size();i++){System.out.println(list.get(i));}// 遍历:第三种foreach循环遍历for (String data:list){     // 因为集合中存放的是String类型   list是集合System.out.println(data);}}
}

输出结果:

十三、演示HashSet集合特点

HashSet集合:无序不可重复2、无序: 这里的无序指的是存进去的顺序和取出来的顺序不同,并且没有下标

代码演示如下:

package com.bjpowernode.javase.collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;/*
HashSet集合:无序不可重复*/
public class HashSetTest01 {public static void main(String[] args) {Set<String> set =new HashSet<>(); // 泛型// 向Set集合中添加元素set.add("hello1");set.add("hello2");set.add("hello3");set.add("hello4");set.add("hello5");set.add("hello5");set.add("hello5");set.add("hello5");set.add("hello5");// 迭代for (String data:set){System.out.println(data);}}
}

输出结果: 

十四、演示TreeSet集合特点

TreeSet集合储存元素特点:1、无序不可重复,但是储存的元素可以自动按照大小顺序排序!称为:可排序集合2、无序: 这里的无序指的是存进去的顺序和取出来的顺序不同,并且没有下标

代码演示如下: 

package com.bjpowernode.javase.collection;
import java.util.*;public class TreeSetTest01 {public static void main(String[] args) {// 创建集合对象Set<String> set =new TreeSet<>();// 添加元素set.add("B");set.add("A");set.add("D");set.add("C");set.add("E");set.add("E");set.add("E");set.add("E");set.add("E");// 遍历for (String data:set){System.out.println(data);}}
}

输出结果:


http://www.taodudu.cc/news/show-7665393.html

相关文章:

  • Windows安装完ADFS后卸载ADFS清除ADFS数据库
  • ADFS服务无法启动的原因排查
  • 更新adfs的证书_Office 365实战系列之三(安装配置ADFS)
  • 更新adfs的证书_Office 365 ADFS Token Signing 证书过期警告问题
  • ADFS 6.3 证书更新
  • ADFS修改默认访问端口
  • adfs sso java_实战:ADFS3.0单点登录系列-总览
  • java adfs sso_Spring SAML ADFS:java.security.InvalidKeyException
  • adfs sp java_SAML 2.0声称不通过ADFS
  • java adfs sso_实战:ADFS3.0单点登录系列-ADFS3.0安装配置
  • Dynamics 365配置ADFS
  • 基于SAML的ADFS认证集成方案
  • adfs 登录逻辑
  • 集成adfs
  • 设计模式 Design Parttern ——桥模式Bridge
  • JavaScript Promise详解 resolve()、reject()、then()、catch()、finally()(包含习题)
  • ABAP 逻辑数据库的循环REJECT
  • IJCAI2023 Summary Reject公布
  • return和reject、resolve的配合使用
  • Linux常用命令——reject命令
  • alpine linux默认账号密码
  • Alpine 安装依赖包
  • vmware安装alpine linux
  • alpine linux nginx,Docker alpine构建nginx
  • alpine安装启动mysql_Alpine Linux常用命令
  • alpine 编译c语言,Alpine Linux配置使用技巧
  • alpine 笔记
  • Alpine基本操作
  • Alpine VMware
  • C++编程之 std::forward