集合、泛型

集合、泛型

集合和数组都是容器,那么他们的区别是什么呢?
数组长度是固定的,集合的长度是可变的。
数组中只能存放同一元素,只可以存放基本数据类型。集合的存储是对象,而且对象的类型可以不一致。
按照存储结构来分,集合可以分为2大类,分别是:
单列集合Collection
双列集合Map
他俩同属于java.util包
Collection集合:
单列集合的根接口,用于存储一系列符合某种规则的元素,他有两个重要的子接口,分别是List和set
List特点:
有序,元素可以重复,有索引
主要有:ArrayList和LinkList
set特点:
元素无序,而且元素不可以重复。
主要有:HashSet和TreeSet
在这里插入图片描述
Collection常用功能:

package com.rongyu.day10;

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

/**
 * 测试Collocation
 */
public class Dome01 {
    public static void main(String[] args) {
        Collection<String> collection = new ArrayList<>();
        //add
        collection.add("张三");
        collection.add("李四");
        collection.add("王五");
        System.out.println(collection);
        //contains 判断集合中是否有该元素 返回布尔值
        System.out.println(collection.contains("张三"));
        //remove删除集合中的元素 返回布尔值
        System.out.println(collection.remove("张三"));
        System.out.println(collection);
        //size
        System.out.println(collection.size());
        //toArray() 转换为一个Object数组
        Object[] objects = collection.toArray();
        for (Object object : objects) {
            System.out.println(object);
        }
        //clear 清空集合内所有元素
        collection.clear();
        System.out.println(collection);
        // isEmpty() 判断集合是否为空 返回布尔值(为空返回true)
        System.out.println(collection.isEmpty());
    }
}

在这里插入图片描述

Iterator迭代器:
用于遍历集合中的所有元素,但是他与collocation接口和Map接口有所不同,Collection和Map主要用于存储元素,但是Iterator主要用于迭代访问。
迭代器的主要方法:
next()返回迭代的下一个元素
hasNext()看还有元素需要迭代不,有的话返回true

package com.rongyu.day10;

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

/**
 * 测试 Iterator 迭代器
 */
public class Dome02 {
    public static void main(String[] args) {
        Collection<String> collection = new ArrayList<>();
        //add
        collection.add("张三");
        collection.add("李四");
        collection.add("王五");
        //Iterator
        Iterator<String> iterator = collection.iterator();
        while (iterator.hasNext()){
            String next = iterator.next();
            System.out.println(next);
        }
    }
}

在这里插入图片描述

注意如果没有判断就进行next操作会报出java.util.NoSuchElementException
迭代器的实现原理:
他在遍历集合时,内部采用指针的方式来跟踪集合中的元素。开始时,他会现在迭代器的第一个元素之前,每次调用一次next方法,指针就会向后移动一位,指向第一个元素并将该元素返回,再次调用也是如此,知道hasnext为false。
增强for循环:

package com.rongyu.day10;

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

/**
 * 增强for循环
 */
public class Dome03 {
    public static void main(String[] args) {
        Collection<String> collection = new ArrayList<>();
        //add
        collection.add("张三");
        collection.add("李四");
        collection.add("王五");
        for (String s : collection) {
            System.out.println(s);
        }
    }
}

在这里插入图片描述
他的内部原理也是iterator迭代器,所以在迭代过程中不能对集合的元素进行增删操作。
泛型:
就是在类中或者方法中预支的使用未知类型。默认为Object类型。
泛型的优点:
将运行时期的ClassCastException,转译成了编译失败;
避免了强制转型的麻烦;
泛型的定义与使用:
类:

package com.rongyu.day10;

/**
 * 定义泛型类
 */
public class Dome04<E> {
    private E e;
    public void setE(E e){
        this.e = e;
    }
    public E getE(){
        return e;
    }
}
package com.rongyu.day10;

/**
 * 测试泛型类
 */
public class TestE {
    public static void main(String[] args) {
        Dome04<String> dome04 = new Dome04<>();
        dome04.setE("张三");
        System.out.println(dome04.getE());
        Dome04<Integer> dome041 = new Dome04<>();
        dome041.setE(12);
        System.out.println(dome041.getE());
    }
}

在这里插入图片描述
方法:

package com.rongyu.day10;

/**
 * 测试泛型的方法
 */
public class Dome05 {
    public static void main(String[] args) {
        Dome05 dome05 = new Dome05();
        dome05.show(12);
        String zhangSan = dome05.show2("ZhangSan");
        System.out.println(zhangSan);
    }
    //定义泛型方法
    public <E> void show(E e){
        System.out.println(e.getClass());
    }
    public <E> E show2(E e){
        return e;
    }
}

在这里插入图片描述
含有泛型的接口:
跟类相似;
可以在实现接口时明确类型;
也可以一直不确定类型,直到创建对象的时候确定类型;
泛型通配符:
当时用泛型类或者接口时,泛型的类型不确定的时候可以通过通配符<?>表示;
注意:泛型不存在继承关系;
泛型上限:
格式:类型名称<? extends 类> 对象名称
意义:只能接收该类型和他的子类;
泛型下限:
格式:类型名称 <? super 类>对象名称
意义:只能接收该类和他的父类型
集合综合案列:(斗地主)

package com.rongyu.day10;

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

/**
 * 集合实现斗地主
 */
public class Dome06 {
    public static void main(String[] args) {
        //准备牌
        List<String> pai = new ArrayList<>();
        //花色
        List<String> huase = new ArrayList<>();
        //数字
        List<String> shuzi = new ArrayList<>();
        //添加花色
        huase.add("♣");
        huase.add("❤");
        huase.add("♦");
        huase.add("♣");
        for (int i = 2; i <= 10; i++) {
            shuzi.add(i+"");
        }
        shuzi.add("A");
        shuzi.add("J");
        shuzi.add("Q");
        shuzi.add("K");
        for (String h : huase) {
            for (String s : shuzi) {
                String card = h + s;
                pai.add(card);
            }
        }
        pai.add("大王");
        pai.add("小王");
        Collections.shuffle(pai);
        //创建3个玩家
        List<String> player01 = new ArrayList<>();
        List<String> player02 = new ArrayList<>();
        List<String> player03 = new ArrayList<>();
        List<String> dipai = new ArrayList<>();
        for (int j = 0; j < pai.size(); j++) {
            String pai1 = pai.get(j);
            if (j>=51){
                dipai.add(pai1);
            }else {
                if (j%3 == 0){
                   player01.add(pai1);
                }else if (j%3 == 1){
                    player02.add(pai1);
                }else {
                    player03.add(pai1);
                }
            }
        }
        //打印
        System.out.println("玩家一:"+player01);
        System.out.println("玩家二:"+player02);
        System.out.println("玩家三:"+player03);
        System.out.println("底牌:"+dipai);
    }
}

在这里插入图片描述
List集合的特点:
1.他是一个存储元素有序的集合。添加时候是什么顺序,存储到集合里面就是什么顺序的。
2.他是一个带索引的集合,通过索引就可以精准的操作集合中的元素。
3.集合中可以存在重复的元素,通过元素的equals方法,来比较是否有相同的元素。
List中常用的几个方法:
get
set
add
remove
List的子类:
ArrayList集合:
存储的底层数数组,所以他的特点是查找快,删除和增加很慢。
LinkedList集合:
底层是链表结构,所以他的添加和删除快。
他提供了大量首尾操作的例子;

package com.rongyu.day10;

import java.util.LinkedList;

/**
 * 测试 LinkedList 集合的首尾操作
 */
public class Dome07 {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();
        //添加到第一个元素
        list.addFirst("a");
        list.addFirst("b");
        list.addFirst("c");
        System.out.println(list);
        //获取元素
        System.out.println(list.getFirst());
        System.out.println(list.getLast());
        //删除元素 返回值是该元素
        System.out.println(list.removeFirst());
        System.out.println(list.removeLast());
        System.out.println(list);
        while (!list.isEmpty()){
            System.out.println(list.pop());//弹出栈顶元素
        }
    }
}

在这里插入图片描述
Set集合:
HashSet集合:
它存储的元素都是不可重复的,并且他是无序的(存储的顺序不一样),底层是由HashMap支持。他根据对象的哈希值来哈希值来确定元素在集合中的存储位置,因此具有很好的存储和查询功能。其保证唯一的方式依赖于:hashcode 和equals 方法
HashSet的存储结构(哈希表):
什么事哈希表:
jdk1.8之前,哈希表底层采用数组加链表实现的,就是使用链表处理冲突,同一hash值的链表都存储在一个链表里,但是当hash值相等的元素过多时,key值得查找速率就会过慢,而在jdk1.8之后,采用数组加链表加红黑树的存储实现,当链表长度超过阈值8时,将链表转化为红黑树,大大减少了查询的时间。
通过对一个数字进行模运算,获得一组下标,存储数据,当产生哈希冲突时,也就是下标一样的情况,会用链表来指针指向他的后一个值。
HashSet存储元素:

package com.rongyu.day10;

import java.util.Objects;

/**
 * 创建学生类
 */
public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

package com.rongyu.day10;

import java.util.HashSet;

/**
 * 测试 hashSet
 */
public class Dome08 {
    public static void main(String[] args) {
        HashSet<Student> hashSet = new HashSet<>();
        Student student1 = new Student("张三",1);
        Student student2 = new Student("李四",2);
        Student student3 = new Student("王五",3);
        Student student4 = new Student("小明",4);
        Student student5 = new Student("小红",5);
        hashSet.add(student1);
        hashSet.add(student2);
        hashSet.add(student3);
        hashSet.add(student4);
        hashSet.add(student5);
        System.out.println(hashSet);
        Student student6 = new Student("张三",1);
        hashSet.add(student6);
        System.out.println(hashSet);
    }
}

总结:
equals默认比较的是地址是否相等,所以需要给student重写equals和hashcode方法才可以去除重复的数据。
LinkedHashSet方法:
是一个有序的。
可变参数:
举例:public void show(int… pram):表示的是他的参数是可以是多个没有的。
Collections:
他是一个集合工具类,用来对集合进行操作。
addAll() 往集合中添加一些元素 返回布尔值
shuffle() 打乱集合的顺序
sort() 将集合进行默认排序
sort(list,Comparator<? super T>);将集合中的数据按照指定的规则排序。
Comparator比较器:

package com.rongyu.day10;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 测试Comparator
 */
public class Dome09 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("abc");
        list.add("dsd");
        list.add("fgd");
        list.add("gfg");
        list.add("hjh");
        Collections.sort(list);
        System.out.println(list);
        System.out.println("------------------------------");
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.charAt(0) - o1.charAt(0);
            }
        });
        System.out.println(list);
    }
}

在这里插入图片描述
简述Comparable和Comparator两个接口的区别:
**Comparable:**强行对实现他的每个类进行排序,称为类的自然排序,类的
compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码
实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进
行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
**comparator:**强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(Collections.sort
或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。
**注意:**要对集合中的元素完成排序,就必须实现Compeable接口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值