侧边栏

集合单列--Colletion

 集合

学习集合的目标:

  1. 会使用集合存储数据
  2. 会遍历集合,把数据取出来
  3. 握每种集合的特性

集合和数组的区别

  1. 数组的长度是固定的。集合的长度是可变的。
  2. 数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类型可以不一致,在开发中一般当对象多的时候使用集合进行存储。

集合框架

JAVASE提供了满足各种需求的API,在使用这些API前,先了解其继承与接口操作架构,才能了解何时采用哪个类,以及类之间如何彼此合作,从而达到灵活应用。

集合按照其存储结构可以分为两,分别是单列集合 java.util.Collection双列集合java.util.Map,

Collection

Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素。

它有两个重要的子接口,分别是java.util.List和java.util.Set。

其中,

  • List的特点是元素有序、元素可重复。
  • Set的特点是元素无序,而且不可重复。

List接口的主要实现类有:

java.util.ArrayList
java.util.LinkedList

Set接口的主要实现类有:

java.util.HashSet
java.util.TreeSet

如图所示:

Collection常用功能

Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。

方法如下:

public boolean add(E e):把给定的对象添加到当前集合中。
public void clear():清空集合中所有的元素。
public boolean remove(E e):把给定的对象在当前集合中删除。
public boolean contains(E e):判断当前集合中是否包含给定的对象。
public boolean isEmpty():判断当前集合是否为空。
public int size():返回集合中元素的个数。
public Object[] toArray():把集合中的元素,存储到数组中。

迭代器

java.util.Iterator接口:迭代器(对集合进行遍历)

有两个常用的方法

  • boolean hasNext() 如果仍有元素可以迭代,则返回 true。

判断集合中还有没有下一个元素,有就返回true,没有就返回false。

  • E next() 返回迭代的下一个元素

取出集合中的下一个元素

Iterator迭代器,是一个接口,我们无法直接使用,需要使用Iterator接口的实现类对象,获取实现类的方式比较特殊

Collection接口中有一个方法,叫iterator(),这个方法返回的就是迭代器的实现类对象

  • Iterator<E> interator() 返回在此 collection的元素上进行迭代的迭代器。

迭代器的使用步骤(重点):

  1. 使用集合中的方法iterator()获取迭代器的实现类对象使用Iterator接口Iterator接口接受(多态)
  2. 使用Iterator接口中的方法hasNext判断还没有没有下一个元素
  3. 使用Iterator接口中的方法next取出集合中的下一个元素
//创建一个集合对象    
Collection<String> coll = new ArrayList();
//向集合中添加元素
coll.add("cai");
coll.add("niao");
/*
1.使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口Iterator接口接收(多态)

注意:
    Iterator<E>接口也是有泛型的,迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型

*/
//多态 接口 实现类对象
Iterator<String> it = cool.interator
while(it.hasNext()){//判断集合有没有下一个元素,从-1开始
    String e = it.next();//取出下一个元素并把指针后移一位
    System.out.println(e);
}

增强for循环

增强for循环:底层使用的也是迭代器,使用for循环的格式,简化了迭代器的书写
是JDK1.5之后出现的新特性

  • Collection<E> extends Iterator<E>:所有的单列集合都可以使用增强for
  • public interface Iterable<T> 实现这个接口允许对象成为“foreach”语句目标。

增强for循环:用来遍历集合和数组

格式

for (集合/数组的数据类型 变量名 : 集合名/数组名){
  System.out.println(变量名);
}

泛型

泛型:是一种未知的数据类型,当我们不知道使用什么数据类型的时候,可以使用泛型

泛型也可以看出是一个变量,用来接受数据类型

  • E e : Element 元素
  • T t : Type 类型

ArrayList集合在定义的时候,不知道集合中都会存储什么类型的数据,所以类型使用泛型

  • E:未知的数据类型
public class ArrayList<E>{
    public boolean add(E e){}
    public E get(int index){}
}

public class ArrayList<String>{
    public boolean add(String e){}//会把数据类型作为参数传递,把String赋值给泛型
    public String get(int index){}
}

创建集合对象,使用泛型
好处:

  1. 避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型
  2. 把运行期异常(代码运行之后会抛出的异常),提升到了编译期(写代码的时候会报错)

弊端:

  1. 泛型是什么类型,只能存储什么类型的数据

创建集合对象,不使用泛型
好处:

  1. 集合不使用泛型,默认的类型就是Object类型,可以存储任意类型的数据

弊端:

  1. 不安全,会引发异常

定义和使用泛型的类

定义含有泛型的方法:泛型定义在方法的修饰符和返回值类型之间

格式:

修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){
  方法体;
}

 

含有泛型的方法,在调用方法的时候确定泛型的数据类型
传递什么类型的参数,泛型就是什么类型

含有泛型的接口,第一种使用方式:定义接口的实现类,实现接口,指定接口的泛型

public interface Iterator<E>{
    E next();
}

Scanner类实现了Iterator接口,并指定接口的泛型为String,所以重写的next方法泛型默认就是String

public final class Scanner implements Iterator<String>{
  publc String next(){}
}

含有泛型的接口第二种使用方式:接口使用什么泛型,实现类就使用什么泛型,类跟着接口走

就相当于定义一个含有泛型的类,创建对象的时候确定泛型的类型

public interface List<E>{
    boolean add(E e);
    E get (int index);
}

public class ArrayList<E> implements List<E>{
    public boolean add(E e){}
    public E get(int index){}
}

泛型的通配符

泛型的通配符:

  • ?:代表任意的数据类型

使用方式:

  • 不能创建对象使用
  • 只能作为方法的参数使用

泛型的上限限定:? extends E 代表使用的泛型只能是E类型的子类/本身
泛型的下限限定:? super E 代表使用的泛型只能是E类型的父类/本身

//泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
public static void getElement1(Collection<? extends Number> coll){}
//泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
public static void getElement2(Collection<? super Number> coll){}

斗地主案例的代码实现(单列)

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

/*  
斗地主综合案例:
    1.准备牌
    2.洗牌
    3.发配
    4.看牌
*/

public class CaiNiao{
    public static void main(String[] args){
    //1.准备牌
    //定义一个存储54张牌的ArrayList集合,泛型使用String
    ArrayList<String> poker = new ArrayList<>();
    //定义两个数组,一个数组存储牌的花色,一个数组存储牌的序号
    String[] colors = {"♥","♦","♣","🍄"};
    String[] numbers = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"};
    //先把大王和小王存储到poker集合中
    poker.add("大王");
    poker.add("小王");
    //循环嵌套遍历两个数组,组装52张牌
    for(String numbers:numbers){
        for (String color : colors){
            //System.out.println(color + numbers);
            //把组装好的牌存储到poker集合中
            poker.add(color + number);
        }
    }
    //    System.out.println(poker);
    /*
    2.洗牌
    使用集合的工具类Collections中的方法
    static void shuffle(List<?> list) 使用默认的随机源对指定列表进行置换。
    
    */
    Collections.shuffle(poker);
    //System.out.println(poker);
    /*
    3.发牌
    */
    //定义4 个集合,存储玩家的牌和底牌
    ArrayList<String> player01 = new ArrayList<>();
    ArrayList<String> player02 = new ArrayList<>();
    ArrayList<String> player03 = new ArrayList<>();
    ArrayList<String> dipai = new ArrayList<>();
    /*
    遍历poker集合,获取每一张牌
    使用poker集合的索引%3给3个玩家轮流发牌
    剩余3张牌给底牌
    注意:
        先判断底牌(i>51),否则牌就发没了
    
    */
    for(int i = 0;i<poker.size();i++){
        //获取每一张牌
        String p = poker.get(i);
        //轮流发牌
        if(i>=51){
            //给底牌发牌
            diPai.add(p);
        }else if (i%3==0){
            //给玩家1发牌
            player01.add(p);
        }else if (i%3==1){
            //给玩家2发牌
            player02.add(p);
        }else if(i%3==2){
            //给玩家3发牌
            player03.add(p);
        }
    }
    //4.看牌
    System.out.println("刘德华:"+player01);
    System.out.println("周润发:"+player02);
    System.out.println("周星驰:"+player03);
    System.out.println("底牌 :"+dipai);
    }
}

 

posted @ 2019-07-19 22:30  菜鸟-传奇  阅读(435)  评论(0编辑  收藏  举报