Java集合

1、集合概述

1.1、什么是集合?有什么用?
数组其实就是一个集合。集合实际上就是一个容器。可以来容纳其它类型的数据。
集合为什么说在开发中使用较多?
集合是一个容器,是一个载体,可以一次容纳多个对象。
在实际开发中,假设连接数据库,数据库当中有10条记录,
那么假设把这10条记录查询出来,在java程序中会将10条
数据封装成10个java对象,然后将10个java对象放到某一个
集合当中,将集合传到前端,然后遍历集合,将一个数据一个
数据展现出来。
1.2、集合不能直接存储基本数据类型,另外集合也不能直接存储java对象,
集合当中存储的都是java对象的内存地址。(或者说集合中存储的是引用。)
list.add(100); //自动装箱Integer
注意:
集合在java中本身是一个容器,是一个对象。
集合中任何时候存储的都是“引用”。
1.3、在java中每一个不同的集合,底层会对应不同的数据结构。往不同的集合中
存储元素,等于将数据放到了不同的数据结构当中。什么是数据结构?数据存储的
结构就是数据结构。不同的数据结构,数据存储方式不同。例如:
数组、二叉树、链表、哈希表…
以上这些都是常见的数据结构。
你往集合c1中放数据,可能是放到数组上了。
你往集合c2中放数据,可能是放到二叉树上了。

你使用不同的集合等同于使用了不同的数据结构。
你在java集合这一章节,你需要掌握的不是精通数据结构。java中已经将数据结构
实现了,已经写好了这些常用的集合类,你只需要掌握怎么用?在什么情况下选择
哪一种合适的集合去使用即可。
new ArrayList(); 创建一个集合,底层是数组。
new LinkedList(); 创建一个集合对象,底层是链表。
new TreeSet(); 创建一个集合对象,底层是二叉树。

1.4、集合在java JDK中哪个包下?
java.util.*;
所有的集合类和集合接口都在java.util包下。
1.5、为了让大家掌握集合这块的内容,最好能将集合的继承结构图背会!!!
集合整个这个体系是怎样的一个结构,你需要有印象。
1.6、在java中集合分为两大类:
一类是单个方式存储元素:
单个方式存储元素,这一类集合中超级父接口:java.util.Collection;

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

在这里插入图片描述
new ArrayList(); 创建一个集合,底层是数组。
new LinkedList(); 创建一个集合对象,底层是链表。
new TreeSet(); 创建一个集合对象,底层是二叉树。

2.继承结构图

一.集合继承结构图

在这里插入图片描述

二.Map集合继承结构图

在这里插入图片描述

3.Collection接口常用方法

关于java.util. Collection接口中常用的方法。
1.Collection中能存放什么元素?
没有使用泛型之前, Collection中可以存Object的所有子类型。
使用泛型之后, Collection中只能存情某个具体的类型
集合后期我们会学泛型语法。日前先不用管。 Collection中什么都能存
只要是Objec的子类型就行。(集合中不能存储基本数据类型,也不能存java对象,只存储java对象的内存地址)
2、 Collection中的常用方法
boolean add(Object e)向集合中添加元素

package com.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionTest01 {
    public static void main(String[] args) {
        Collection collection =new ArrayList();
        collection.add(100);//自动装箱,实际是放进去了一个对象的内存地址
        collection.add(new Object());
        collection.add(true);//自动装箱
    }
}

2、 Collection中的常用方法
boolean add(Object e) 向集合中添加元素
int size() 获取集合中元素的个数
void clear() 清空集合
boolean contains(Object o)判断当前集合中是否包含元素o,包含返回true,不包含返回false
boolean remove(Object o)删除集合中的某个元素。

import java.util.ArrayList;
import java.util.Collection;

public class CollectionTest01 {
    public static void main(String[] args) {
        //创建一个集合对象
        // Collection c= new Collection();/接口是抽象的,无法实例化。
        //多态
        Collection collection =new ArrayList();
        //测试Collection接口中的常用方法
        collection.add(100);//自动装箱(java5的新特性),实际上是放进去了一个对象的内存地址。 Integer x= new Integer()
        collection.add(new Object());
        collection.add(true);
        collection.add(new Student());
        System.out.println(collection.size());
        //清空集合
        collection.clear();
        System.out.println(collection.size());
        collection.add("lupeng");
        collection.add("yinying");
        collection.add("ying");
        collection.add(1);
        //判断集合中是否包含lupeng
        boolean flay=collection.contains("lupeng");
        System.out.println(flay);
        boolean flay2=collection.contains("zhang");
        System.out.println(flay2);
        //获取集合中元素的个数
        System.out.println("删除之前的size="+collection.size());
        collection.remove("yinying");
        System.out.println("删除之后的size="+collection.size());
        //先判断集合是否为空,清空后再判断一次
        boolean flag1=collection.isEmpty();
        System.out.println("是否为空前"+flag1);
        collection.clear();
        boolean flag2=collection.isEmpty();
        System.out.println("是否为空后"+flag2);
        collection.add("lupeng");
        collection.add(730);
        collection.add("ying");
        //将集合转换数组(了解)
        Object[] obj=collection.toArray();
        for (int i=0;i<obj.length;i++){
            Object o=obj[i];
            System.out.println(o);
        }
    }
}
class Student{

}

4.Collection集合迭代

一.实例

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionTest02 {
    public static void main(String[] args) {
        //注意:以下讲解的遍历方式/迭代方式,是所有 Collection通用的一种方式。
        //在Map集合中不能用。在所有的 Collection以及子类中使用。
        //创建集合对象
        Collection collection=new ArrayList();
        collection.add("abc");
        collection.add(1314);
        collection.add("def");
        collection.add(new Object());
        collection.add(1314);
        //对集合 Collection进行遍历/迭代
        //第一步:获取集合对象的迭代器对象Iterator
        Iterator it= collection.iterator();

        /*
        第二步:通过以上获取的迭代器对象开始迭代/遍历集合。
        以下两个方法是迭代器对象Iterator中的方法
        boolean hasNext()如果仍有元素可以迭代,则返回true
        Object next()返回迭代的下一个元素。*/
        while(it.hasNext()){
     //未规定泛型,默认都是object类型
            System.out.println(it.next());
            //只不过在输出的时候会转换成字符串,因为这里println会调用toString()方法
        }
    }
}

abc
1314
def
1314
java.lang.Object@723279cf
同时说明了ArrayList集合有序且可以重复

二.原理图

原理演示,但注意集合里面存储都是对象的内存地址,写上abc 、def只是方便演示
在这里插入图片描述

三.集合方法解析

1.contains方法解析

深入Collection集合的 contains方法
boolean contains(Object o)
判断集合中是否包含某个对象o
如果包含返回true,如果不包含返回 false
contains方法是用来判断集合中是否包含某个元素的方法,那么它在底层是怎么判断集合中是否包含某个元素的呢
调用了 equals方法进行比对。
equals方法返回true,就表示包含这个元素。
String类已经重写了equals方法所以是true

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("abc");
        String s2=new String("def");
        String x=new String("abc");
        c.add(s1);
        c.add(s2);
        System.out.println(c.size());
        System.out.println(c.contains(x));
    }
}

2
true

内存图在这里插入图片描述

2.equlas方法和remove方法对比

//package com.javase.collection;

import java.util.ArrayList;
import java.util.Collection;

public class CollectionTest05 {
    public static void main(String[] args) {
        Collection c=new ArrayList();
        User u1=new User("jack");
        c.add(u1);
        User u2=new User("jack");
        System.out.println(c.contains(u2));
        //未重写equals方法,所以false
        //重写后true
        c.remove(u2);
        //未重写equals方法,size为1
        //重写后0
        System.out.println(c.size());
        Collection c2=new ArrayList();
        String s1=new String("hellow");
        String s2=new String("hellow");
        c2.add(s1);//s1.equals(s2) java认为s1和s2是一样的。删除s1就是删除s2
        c2.remove(s2);
        //集合中元素的个数
        System.out.println(c2.size());
    }
}
class User{
    private String name;
    public User(){}
    public User(String name){
        this.name=name;
    }
    public boolean equals(Object obj){
        if(obj==null||!(obj instanceof User)) return false;
        User user=(User)obj;
        if (name == user.name){
            return true;
        }
        return false;
    }
}

true
0
0

3.关于集合中元素的删除remove()

关于集合元素的remove
重点:当集合的结构发生改变时,迭代器必须重新获取,如果还是用以前老的送代器,会出现
7: java util. ConcurrentModificationException
重点:在送代集合元素的过程中,不能调用集合对象的 remove方法,删除元素
c, remove(o);迭代过程中不能这样

会出现:java.util.ConcurrentModificationException
重点:在送代元素的过程当中,一定要使用送代器 Iterator的 remove方法,删除元素
不要使用集合自带的remove方法删除元素。

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionTest06 {
    public static void main(String[] args) {
        Collection c=new ArrayList();
 /*
注意:此时获取的迭代器,指向的是那是集合中没有元素状态下的送代器。
一定要注意:集合结构只要发生改变,迭代器必须重新获取。
当集合结构发生了改变,送代器没有重新获取时,调用next()方法时:java.utit.ConcurrentModificatiolException*/
/*        Iterator it2=c.iterator();
        c.add(1);
        c.add(2);
        c.add(3);
        Iterator it=c.iterator();
        while(it.hasNext()){
            Object obj=it.next();

            System.out.println(obj);
        }*/
        Collection c2=new ArrayList();
        c2.add("ying");
        c2.add("lupeng");
        c2.add("like");
        Iterator it=c2.iterator();
        while(it.hasNext()){
            Object obj=it.next();
            //c2.remove(obj); error
            /*          //删除元素
//删除元素之后,集合的结构发生了变化,应该重新去获取送代器
//但是,循环下一次的时候并没有重新获成送代器,所以会出现异常:java.util.ConcurrentModificationException
//出异常根本原因是:集合中元素删除了,但是没有更新送代器(迭代器不知道集合交化了)
//c2. remove(obj);/直接通过集合去删除元素,没有通知迭代器。(导致迭代器的快照和原集合状态不同.)
//使用迭代器来删除可以吗?
            迭代器去删除时,会自动更新迭代器,并且更新集合(删除集合中的元素)*/

            it.remove();//删除的一定是迭代器指向的当前元素
            System.out.println(obj);
        }
        System.out.println(c2.size());
    }
}

ying
lupeng
like
0

4.List接口特有方法

测List接口中常用方法
1、List集合存储元素特点:有序可重复
有序:List集合中的元素有下标。
从0开始,以1递增。
可重复:存储一个1,还可以再存储1
2、List既然是 Collection接口的子接口,那么肯定List接囗有自己特色的方法
以下只列出List接口特有的常用的方法
void add (int index, Object element)
Object get(int index)
int indexof(Object o)
int lastIndexof(Object o)
Object remove(int index)
Object set(int index, Object element)

import java.util.ArrayList;
import java.util.Iterator;

public class ListTest01 {
    public static void main(String[] args) {
//创建List类型的集合。
//List mylist new Linkedlist();
//List mylist new Vector();
        ArrayList myList=new ArrayList();
        //添加元素
        myList.add(1);//默认都是向集合末尾添加元素
        myList.add("A");
        myList.add("B");
        myList.add("B");
        myList.add("c");

        //这个方法用的不多,因为对ArrayList集合说效率比较低
        myList.add(1,"ying");        //在列表的指定位置插入指定元素(第一个参数是下标) 
        //迭代
        Iterator it=myList.iterator();
        while(it.hasNext()){
            Object obj=it.next();
            System.out.println(obj);
        }
        System.out.println("=======================================");
        //根据下标获取元素
        Object obj=myList.get(0);
        System.out.println(obj);
        System.out.println("=============");
        //因为有下标,所以List集台有自己比较特殊的遍历方式
        //通过下标遍历.List集合特有的方式,Set没有。
        for (int i=0;i<myList.size();i++){
            System.out.println(myList.get(i));
        }
        //获取指定对象第一次出现处的索引
        System.out.println(myList.indexOf("B"));
        //获取指定对象最后一次出现处的索引。
        System.out.println(myList.lastIndexOf("B"));
        //删除指定下标位置的元素
        //删除下标为0的元素
        myList.remove(0);
        //修改指定位置的元素
        myList.set(1,"lupeng");
        System.out.println("===============");
        //遍历集合
        for (int i=0;i<myList.size();i++){
            System.out.println(myList.get(i));
        }
    }
}

1
ying
A
B
B
c
+++++++++++++++++++++++++++++
1
+++++++++++++++++++++++++++++++++++
1
ying
A
B
B
c
3
4
++++++++++++++++++++
ying
lupeng
B
B
c

一.ArrayList集合

1.概述

1、默认初始化容量10(底层先创建了一个长度为0的数组,当添加第一个元素的时候,初始化容量10。)
2、集合底层是一个Object[]数组。
构造方法
new Arraylist;
new Arraylist(20)
4 arraylist集合的扩容
原容量的1.5倍
ArrayList集合底层是数组,怎么优化?
尽可能少的扩容。因为数组扩容效率比较低,建议在使用 ArrayList集合
的时候预信计元素的个数,给定一个初始化容量。
5、数组优点:
检索效率比较高。(每个元素占用空间大小相同,内存地址是连续的,知道首元素内存地址,然后知道下标,通过数学表达式计算出元素的内存地址,所以检索效率最高。)
6、数组缺点:
随机增删元素效率比较低。
7、向数组末尾添加元素,效率很高,不受影响。
8、面试宫经常问的一个问题?
这么多的集合中,你用哪个集合最多?
答: Arraylist集合。
因为往数组末尾添加元素,效率不受影响。
另外,我们检索/查找某个元素的操作比较多。

public class ArrayListTest01 {
    public static void main(String[] args) {
        List list=new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);
        list.add(7);
        list.add(8);
        list.add(9);
        list.add(10);
        System.out.println(list.size());
/*        int newCapacity = ArraysSupport.newLength(oldCapacity,
                minCapacity - oldCapacity, *//* minimum growth *//*
                oldCapacity >> 1           *//* preferred growth *//*);*/
        list.add(11);
        System.out.println(list.size());
    }
}

10
11

2.ArrayList集合另一个构造方法

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

public class ArrayListTest02 {
    public static void main(String[] args) {
        List myList1=new ArrayList();
        //用指定初始容量构造一个空列表
        //初始化容量为10
        //第二种带参数的构造方法初始化容量为100
        List myList2=new ArrayList(100);
      
        Collection c =new HashSet();
          //创建一个 Hashset集合
        c.add(10);
        c.add("ying");
        c.add("lu");
        //通过这个构造方法就可以将HashSet集合转换成List集合。将haseset集合传进去就是下面c
        List myList3=new ArrayList(c);
        for (int i=0;i<myList3.size();i++){
            System.out.println(myList3.get(i));
        }
    }
}

ying
lu
10

二.LinkedList源码分析

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class LinkListTest01 {
    public static void main(String[] args) {
        List list=new LinkedList();
        list.add("a");
        list.add("b");
        list.add("c");
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
        // Linkedlist集合有初始化容量吗?没有。
        //最初这个链表中没有任何元素。 first和last引用都是 null
        //不管是 Linkedlist还是 Arraylist,以后写代码时不需要关心具体是哪个集合。
        //因为我们要面向接口编程,调用的方法部是接口中的方法。
        List list1=new ArrayList();//这样写表示底层用了数组
        List list2=new LinkedList();//这样写表示底层用了双向链表
    }
}

在这里插入图片描述

三.Vector集合源码解析

Vector
1、底层也是一个数组。
2、初始化容量:10
3、怎么扩容的?
扩容之后是原容量的2倍
10–)>20–)40–>80
4、 Arraylist集合扩容特点:
ArrayList容量扩容为原来两倍
5、 Vector中所有的方法都是线程同步的,都带有 synchronized关键字
是线程安全的。效率比较低,使用较少了。
6、怎么将一个线程不安全的 realist集合转换成线程安全的呢?
使用集合工具类
java util. Collections
java.utiL. Collection是集合接口
java.utiL. Collections是集台工具类。

import java.util.*;

public class VectorTest {
    public static void main(String[] args) {
        Collection vector=new Vector();
        vector.add(1);
        vector.add(2);
        vector.add(3);
        vector.add(4);
        vector.add(5);
        vector.add(6);
        vector.add(7);
        vector.add(8);
        vector.add(9);
		vector.add(10);
        //满容后扩容2倍
        vector.add(11);
        Iterator it=vector.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        Collection mylist=new ArrayList();//非线程安全
        Collections.synchronizedCollection(mylist);//变成线程安全

    }
}

5.泛型

一.概述

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

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class genericTest01 {
    public static void main(String[] args) {
 /*       List myList=new ArrayList();
        Cat c=new Cat();
        Bird b=new Bird();
        myList.add(c);
        myList.add(b);
        Iterator it=myList.iterator();
        while (it.hasNext()){
        //没有这个语法,通过迭代器取出的就是Obect
            Object obj=it.next();
            if(obj instanceof Animal){
            //obj中没用move方法,无法调用,需要向下转型
                Animal a=(Animal)obj;
                a.move();
            }
        }*/
        //使用JDK5之后的泛型机制
        //使用泛型List<Animal>之后,表元List集合中只允许存Animal类型的数据。
        // 用泛型来指定集合中存储的数据类型。
        //这样使用泛型之后,表示list集合只允许存储Animal类型的数据
        List<Animal> myList1=new ArrayList<Animal>();
       // 指定ist集合中只能存 Animal,那么存体 tring就编译报错了
        //这样用了泛型之后,集合中元素的数据类型更加统-了。
        /*myList1.add("abc");*/
        Cat c=new Cat();
        Bird b=new Bird();
        myList1.add(c);
        myList1.add(b);
        //获取迭代器
        //这个表示迭代器迭代的是Animal类型
        Iterator<Animal> it=myList1.iterator();
        while(it.hasNext()){
 //使用泛型之后,每一次送代返回的数据都是 Animal类型。
//Animal a= it. next();
//这里不需要迸行强制类型转换了。接调用。
//a move();
//调用子类型特有的方法还是需要向下转换的!
            Animal a=it.next();
            if (a instanceof Cat){
                Cat c1=(Cat)a;
                c1.CatchMouse();
            }else if(a instanceof Bird){
                Bird b1=(Bird)a;
                b1.fly();
            }
        }

    }
}
class Animal{
        public void move(){
            System.out.println("动物在移动");
        }
}
class Cat extends Animal{
    public void CatchMouse(){
        System.out.println("猫抓老鼠");
    }
}
class Bird extends Animal{
    public void fly(){
        System.out.println("鸟在飞翔");
    }
}

猫抓老鼠
鸟在飞翔

二.自定义泛型

自定义泛型可以吗?可以
自定义泛型的时候,<>尖括号中的是一个标识符,随使写。
java源代码中经常出现的是

E是 ELement单词首字。
T是Type单词首字。

public class genericTest03<标识符随便写> {
    public void doSome(标识符随便写 o){
        System.out.println(o);
    }
    public static void main(String[] args){
        //new对象的时候指定了泛型是:String类型
        genericTest03<String> gt=new genericTest03<>();
        gt.doSome("abc");
        //gt.doSome(100); 类型不匹配
        System.out.println("++++++++++++++++++");
        genericTest03<Integer> gt2=new genericTest03<>();
        gt2.doSome(100);
        System.out.println("================================");

        MyIterator<String> m1=new MyIterator<>();
        String s1=m1.get();

        MyIterator<Animal> m2=new MyIterator<>();
        Animal a=m2.get();
        
        //不用泛型是Object类型
        genericTest03 gt3=new genericTest03();
        gt3.doSome(new Object());
    }
}
class MyIterator<E>{
   public E get(){
       return null;
   }

}

abc
++++++++++++++++++
100

6.foreach遍历集合

一.语法

增强for( foreach)
以下是语法
for(元素类型 变量名:数组或集合){
System.out. println(变量名);
}

1.数组


}
public class ForEachTest01 {
    public static void main(String[] args) {
        int[] arr={12,24,53,232,43};
        for (int i=0;i< arr.length;i++){
            System.out.println(arr[i]);
        }
        System.out.println("+++++++++++++++++++");
        //foreach有一个缺点:没有下标
        for (int data:arr){
            //data就是数组中的元素(数组中的每一个元素)
            System.out.println(data);
        }
    }
}

12
24
53
232
43
+++++++++++++++++++
12
24
53
232
43

2.集合

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ForEachTest02 {
    public static void main(String[] args) {
        List<String> strlist=new ArrayList<>();
        strlist.add("lupeng");
        strlist.add("come on");
        strlist.add("never give up");

        //遍历方式,使用迭代器遍历
        Iterator<String> it=strlist.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }

        //使用下标方式(只针对有下标的集合)
        for(int i=0;i<strlist.size();i++){
            System.out.println(strlist.get(i));
        }

        //使用foreach
        for(String s:strlist){ //因为泛型使用的是String类型,所以是String s
            System.out.println(s);
        }
    }
}

lupeng
come on
never give up
lupeng
come on
never give up
lupeng
come on
never give up

7.简单演示HashSet和TreeSet

一.HashSet

无序不重复集合

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetTest01 {
    public static void main(String[] args) {
        //遍历
/*      hello1
        hello3
        hello5
        hello4
        1、存时顺序和取出的顺序不同。
        2、不可重复
        3、放到ash5et集合中的元素实际上是放到HashMap*/
        Set<String> str=new HashSet<>();
        str.add("fuck1");
        str.add("fuck3");
        str.add("fuck5");
        str.add("fuck4");
        str.add("fuck3");
        Iterator<String>it =str.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        str.add("1");
        str.add("2");
        str.add("fuck1");
        str.add("1");
        //使用增强for
        for(String s:str){
            System.out.println(s);
        }
    }
}

fuck3
fuck4
fuck5
fuck1
1
2
fuck3
fuck4
fuck5
fuck1

TreeSet

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


import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class TreeSetTest01 {
    public static void main(String[] args) {
        Set<String> hashset=new HashSet<>();
        hashset.add("A");
        hashset.add("M");
        hashset.add("C");
        hashset.add("F");
        hashset.add("C");
        Iterator<String> it =hashset.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }

    }
}

A
C
F
M

7.Map

将开启新的章节

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值