Collection 单列集合的7种存出方法 泛型 增强for 迭代器的实现原理 Collections 可变参数()

集合概述

集合:集合是java中提供的一种容器,可以用来存储多个数据。

  • 集合和数组既然都是容器,它们有啥区别呢?
  • 数组的长度是固定的。集合的长度是可变的。
    数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类型可以不一致。在开发中一般当对象多的时候,使用集合进行存储

集合概述

集合按照其存储结构可以分为两大类,分别是单列集合java.util.Collection和双列集合java.util.Map
Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.Listjava.util.Set。其中,List的特点是元素有序、元素可重复。Set的特点是元素无序,而且不可重复。List接口的主要实现类有java.util.ArrayListjava.util.LinkedListSet接口的主要实现类有java.util.HashSetjava.util.TreeSet
整个集合类的继承体系。

在这里插入图片描述
橙色框里填写的都是接口类型
蓝色框里填写的都是具体的实现类
集合本身是一个工具,它存放在java.util包中。在Collection接口定义着单列集合框架中最最共性的内容。

Collection相关Api

单列集合(List和Set)通用的一些方法
方法如下:

  • int size(); 获取集合的长度
  • boolean isEmpty(); 判断集合是否为空
  • void clear(); 清空集合
  • boolean contains(Object element); 判断当前元素是否存在于集合内
  • boolean add(Object element); 向集合中添加元素
  • boolean remove(Object element); 根据参数删除集合中的元素
  • boolean containsAll(Collelction c); 判断一个集合中的元素是否存在于当前的集合中
  • boolean addAll(Collelction c); 向一个集合内部添加另一个集合
  • boolean removeAll(Collelction c); 在一个集合中删除参数指定的集合
  • boolean retionAll(Collection c); 获取两个集合的交集
  • Object[] toArray 把一个集合转换为Object数组
  • <T>T[] toArray(T[] a); 指定操作的泛型类型,并把内容返回
  • Iterator<E>Iterator(); 为iterator接口实例化
  • booleam equals(Object o);
  • int hashCode();
    本接口中一共定义了 15个方法

开发中不会直接使用 Collection 接口。而使用其操作的子接口:List、Set

Collection增加Api

boolean add(Object element); 向集合中添加元素

boolean addAll(Collelction c); 向一个集合内部添加另一个集合

Collection删除Api

boolean add(Object element); 向集合中添加元素

boolean addAll(Collelction c); 向一个集合内部添加

Collection修改Api

public void clear() :清空集合中所有的元素。

list.clear();

Collection判断Api

boolean isEmpty(); 判断集合是否为空

boolean contains(Object element); 判断当前元素是否存在于集合内

boolean containsAll(Collelction c); 判断一个集合中的元素是否存在于当前的集合中

boolean retionAll(Collection c); 获取两个集合的交集

Collection获取功能

int size(); 获取集合的长度

Object[] toArray 把一个集合转换为Object数组

// 获取 集合容器的大小
int size = list.size();

把一个集合转换为Object数组
Collection list = new ArrayList();
Object[] oo = list.toArray();

项目2 泛型入门

泛型:可以简单理解为限制了集合中存入的数据的类型。
泛型可以定义在 类 方法 接口前面
泛型中的类型包括:

Object String Number Integer

泛型各个定义的语法

在类中

修饰符 class类名<代表泛型的变量> {
}

泛型类实例:

//MVP在这里代表 未知的一种数据类型 未来传递什么就是什么类型
public class One <MVP>{
//有参数无返回值的方法
public void show(MVP mvp){
 System.out.println(mvp);
}
public static<MVP> getShow(MVP mvp){
return mvp;
}
}

在类中什么时候被确定的?

在创建对象的时候确定

在方法中

定义格式

修饰符 返回类型 方法名参数(){
}

实例:

public <T> void show(ACE ace){
System.out.println(ace.getClass());
}

方法中什么时候被确定的?

调用方法时,确定泛型的类型

在接口中

格式:

修饰符 interface 接口名{ }

类型什么时候确定?

有两种方式 比如下方实例

实例:

//一 定义接口
public interface C1<Q> {
    public abstract void show();
    public abstract Q getQ();
}
//2-1 定义实现类——确定泛型类型
public class MyImp implements C1<String>{
@Override
 public void show(String s){
 //省略
 }
  public String getQ(){
  //省略
  }
}
//此时泛型Q的类型就是String
//—————————————————————————
//2-2 定义实现类——不确定泛型类型(子类必须也是泛型类)
public class MyImp2<Q> implement C1<Q>{
@Override
 public void show(Q q){
 //省略
 }
  public Q getQ(){
  //省略
  }
}
//第三 确定泛型,需要新的实现类	
public class Demo{
 public static void main(String[] args) {
 //创建对象,定义实现类型
 MyImp2<String>  my = new MyImp2<String>();
 my.add("aa");
 
 }
}

泛型通配符

当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。

不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符

通配符基本使用

public static void getElement(Collection<?> coll){}
//?代表可以接收任意类型

通配符高级使用----受限泛型

JAVA的泛型中还可以指定一个泛型的上限下限。取决于extends和super关键字

泛型的上限

  • 格式: 类型名称 <? extends 类 > 对象名称
  • 意义: 只能接收该类型及其子类

泛型的下限

  • 格式: 类型名称 <? super 类 > 对象名称
  • 意义 : 只能接收该类型及其父类型
  • 比如:现已知Object类,String 类,Number类,Integer类,其中Number是Integer的父类

定义集合时,同时定义集合中元素的类型。

好处

  • 增强程序的可读性和稳定性。
  • 避免了强制类型转换的麻烦。
  • 将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
public class Demo06{
	
	public static void main(String[] args) {
	/*	
		Set s = new HashSet();
		s.add("aaa");
		s.add("bbb");
		s.add(111);
		s.add(222);
		s.add(new Date());
		s.add(new User(1,"aaa",20));
		System.out.println(s.size());
		
		for(Object obj:s){
			System.out.println(obj);
		}
	*/
		Set<String> s = new HashSet<>();
		s.add("aaa");
		s.add("bbb");
		s.add("ccc");
		//s.add(111);
		
		Set<Integer> s2 = new HashSet<>();
		s2.add(1);
		s2.add(2);
		//s2.add("aaa");
	}
}

项目3 Iterator迭代器

Iterator接口

java.util.IteratorIterator接口也是Java集合中的一员,但它与CollectionMap接口有所不同,Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。

迭代:即Collection集合元素的通用获取方式。
在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。

Iterator接口的常用方法如下:

public E next():返回迭代的下一个元素。 public boolean hasNext():如果仍有元素可以迭代,则返回 true。

案例展示:

public class IteratorDemo {
  	public static void main(String[] args) {
        // 使用多态方式 创建对象
        Collection<String> coll = new ArrayList<String>();

        // 添加元素到集合
        coll.add("串串星人");
        coll.add("吐槽星人");
        coll.add("汪星人");
        //遍历
        //使用迭代器 遍历   每个集合对象都有自己的迭代器
        Iterator<String> it = coll.iterator();
        //  泛型指的是 迭代出 元素的数据类型
        while(it.hasNext()){ //判断是否有迭代元素
            String s = it.next();//获取迭代出的元素
            System.out.println(s);
        }
  	}
}

迭代器的实现原理

在这里插入图片描述
在调用Iterator的next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历

项目4 增强for

增强for循环(也称for each循环),它的内部原理也是个Iterator迭代器。目标只能是Collection或者是数组。
作用:

专门用来遍历数组和集合的

缺点:

遍历的过程中,不能对集合中的元素进行增删操作。

格式:

for(元素的数据类型 变量 : Collection集合or数组){
//写操作代码
}

在这里插入图片描述

项目5 set

set和list一样同样继承Collection接口

它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格
set集合特点:

无序和唯一

项目6set实现类HashSet

HashSet原理:用Hash技术实现的Set结构。

如果对象的hashCode值是不同的,那么HashSet会认为对象是不可能相等的
因此我们自定义类的时候需要重写hashCode,来确保对象具有相同的hashCode值。

总结:

元素的哈希值是通过元素的hashcode方法 来获取的, HashSet首先判断两个元素的哈希值,如果哈希值一样,接着会比较equals方法 如果 equls结果为true ,HashSet就视为同一个元素。如果equals 为false就不是同一个元素。

哈希值相同equals为false的元素是怎么存储呢,就是在同样的哈希值下顺延(可以认为哈希值相同的元素放在一个哈希桶中)。也就是哈希一样的存一列。

项目7 LinkedHashSet

是链表和哈希表组合的一个数据存储结构。

Set set = new LinkedHashSet();

项目8 TreeSet

TreeSet是一个可排序集合,基于红黑树(自平衡二叉树),默认按元素的自然顺序升序排列。

TreeSet t = new TreeSet<>();

当存入的是基本数据类型和字符串时,TreeSet有自动升序排列的能力。而当存入的是自定义引用类型,遍历时会抛出异常

项目9TreeSet集合排序的两种方式

第一种Comparable接口

第一种方式让元素自身具备比较性,也就是元素需要实现Comparable接口,重写compareTo 方法
重写:

第一 子类实现 Comparable接口的方法 implements
implements Comparable<属性范围>

第二 重写方法
idea中 generate——compareTo;

第三 方法排序注意

compareTo 方法:this和参数的比较。

  • 返回正数 this比参数大 (this排在参数后面)
  • 返回负数 this比参数小 (this排在参数前面)
  • 返回零 this和参数相等(认为是重复数据)
    return this.price-o.getPrice() ; 升序
    return o.getPrice()-this.price ;降序

第二种Comparator接口

当元素自身不具备比较性,或者元素自身具备的比较性不是所需的。那么这时只能让容器自身具备。

定义一个类实现Comparator 接口,重写compare方法。并将该接口的子类对象作为参数传递给TreeSet集合的构造方法。

重写:

public int compare(Teacher t1, Teacher t2) {
        // t1>t2  返回整数
        // t1<t2 返回负数
        // t1==t2 返回0
        //return t1.getId()-t2.getId();
        return t1.getName().compareTo(t2.getName());
    }

注意:当Comparable比较方式,及Comparator比较方式同时存在,以Comparator比较方式为主。

TreeSet案例

需求:
将字符串中的数值进行排序。
例如String str=“8 10 15 5 2 7”;
使用 TreeSet完成。

思路:
1、将字符串切割。
2、可以将这些对象存入TreeSet集合。
因为TreeSet自身具备排序功能。

实例:

public class Demo1 {
    public static void main(String[] args) {
        String str = "8 10 15 21 16";
        String[] sp = str.split("\\s+");

        TreeSet<Integer> t = new TreeSet<>();
        for(String s:sp){
            t.add(Integer.parseInt(s));
        }

        System.out.println(t);
    }
}

项目10 list接口

在这里插入图片描述
list特点
List接口是Collection的子接口,实现List接口的容器类中的元素是有顺序的,而且可以重复。
有序
可重复
内部结构为 数组结构和链表结构
主要实现类有 ArrayListLinkedList

list 独有的方法取 改 填 删

Object get(int index); 通过索引获取元素

Object set(int index,Object element); 修改某出索引元素

void add(int index,Object element); 在某处索引添加元素

Object remove(int index); 根据索引删除元素

项目11 ArrayList

java.util.ArrayList合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList`是最常用的集合

项目12 LinkedList

LinkedList是一个双向链表
如图:
在这里插入图片描述

实际开发中对一个集合元素的添加与删除经常涉及到首尾操作

LinkedList提供了大量首尾操作的方法

  • public void addFirst(E e):将指定元素插入此列表的开头。
  • public void addLast(E e):将指定元素添加到此列表的结尾。
  • public E getFirst():返回此列表的第一个元素。
  • public E getLast():返回此列表的最后一个元素。
  • public E removeFirst():移除并返回此列表的第一个元素。
  • public E removeLast():移除并返回此列表的最后一个元素。
  • public boolean isEmpty():如果列表不包含元素,则返回true。

项目12——*** ArrayList与LinkedList的区别?

面试常考

  • 他们都是线性表,但是ArrayList基于数组(顺序存储),LinkedList基于链表(链式存储)
  • 由于实现的不同,ArrayList在随机访问元素时性能较高,插入和删除元素时效率较低,LinkedList则反之。

项目13 Vector和Stack(栈)

Vector: 描述的是一个线程安全的ArrayList。

  • Vector与ArrayList的区别

ArrayList: 单线程效率高。

Vector : 多线程安全的,所以效率低。

常用方法 取尾 指定索引 取全部封装 Enumeration

void addElement(E obj) 在集合末尾添加元素

E elementAt( int index) 返回指定角标的元素

Enumeration elements() 返回集合中的所有元素,封装到Enumeration对象中

Enumeration接口: 枚举

boolean hasMoreElements() 测试此枚举是否包含更多的元素。

E nextElement() 如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。

public static void main(String[] args) {
    Vector v = new Vector();
    v.addElement("aaa");
    v.addElement("bbb");
    v.addElement("ccc");
    System.out.println( v );
    System.out.println( v.elementAt(2) );   // ccc
    // 遍历Vector遍历
    Enumeration ens = v.elements();
    while ( ens.hasMoreElements() ){
        System.out.println( ens.nextElement() );
    }
}

Stack(栈)

常用方法:

booleanempty() 测试堆栈是否为空。
Epeek() 查看堆栈顶部的对象,但不从堆栈中移除它。
Epop() 移除堆栈顶部的对象,并返回该对象作为此函数的值。
Epush(E item) 把项压入堆栈顶部。
intsearch(Object o) 返回对象在堆栈中的位置,以 1 为基数。

Stack类是Vector类的子类。特点是先进后出。

项目14可变参数()

我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以对其简化成如下格式

修饰符 返回值类型 方法名(参数类型… 形参名){ }

修饰符 返回值类型 方法名(参数类型[] 形参名){ }

  /*
     * 完成数组  所有元素的求和 原始写法
     
      public static int getSum(int[] arr){
        int sum = 0;
        for(int a : arr){
            sum += a;
        }
        
        return sum;
      }
    */
    //可变参数写法
    public static int getSum(int... arr) {
        int sum = 0;
        for (int a : arr) {
            sum += a;
        }
        return sum;
    }

输出完全相等

项目15 Collections

java.utils.Collections是集合工具类,用来对集合进行操作。

方法有:

sort(List<T> list); 对List即可进行默认排序

addAll(Collection<T>,T...e);向集合中添加可变参数元素

fill(List<E> list, E e):将list集合中的所有元素都填充为元素e

int frequency(Collection<E> c, E e):返回在集合c中的元素e的个数

max、min:获取集合的最大值或者最小值

replaceAll(List<E> list, E oldVal, E newVal):将集合list中的所有指定老元素oldVal都替换成新元素newVal

reverse(List<E> list):将参数集合list进行反转

shuffle(List<E> list):将list集合中的元素进行随机置换

swap(List<E> list, int a, int b):将a索引和b索引的元素进行交换

synchronizedXxx方法系列:将一个线程不安全的集合传入方法,返回一个线程安全的集合

contains API源码

判断一个对象中是否拥有某个属性

 public boolean contains(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext())
                if (it.next()==null)
                    return true;
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return true;
        }
        return false;
    }
    ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值