Java重点部分之集合

前言

近来在学习算法,刚入门算法,属实是有点吃力,一个力扣的简单题目做一个多小时,悔当初没有好好学算法,当初以为只要学好一门语言和框架就可以了,但是后来发现算法是灵魂,算法不精通那不管学什么也都是捉襟见肘啊。但java这方面的知识也不能落下呀,最近打算开发一个汇总Java SE的项目,于是先来博客把那些重点的知识再串一下吧,今天先从集合+泛型开始,集合那可是相当重要啊!话不多说,整起~

Collection接口

Java集合框架的根是两个接口:Collection和Map,根据Collection和Map的架构,Java中的集合可以分为3类:List是有序集合,他会记录每次添加元素的顺序,元素可以重复;Set是无序集合,不记录元素添加的顺序,元素不可以重复;Map是键值对的集合,每个元素都有键Key和值value对应组成,键值和取值分别存储,键值是无序集合Set,取值是有序集合List。
collenction是单列集合最顶级的接口
在这里插入图片描述
在这里插入图片描述

注:新建对象的时候可以用new 对象名().var,回车,即可。
迭代器是Collection集合通用的取出数据的方式。

Collection<String> c = new ArrarList<>(); 
c.add("吴哥"); c.add("海哥");
Iterator it = c.iterator();
while(it.hasNext()){
    
    
	String n = (String)it.next();
 	System.out.println(n);
 }

Arraylist集合操作

package cn.gather;

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

public class collection {
    
    
    /**
     *创建一个AeeayList集合,用到了多态的概念,
     * 泛型是String
     * 分别使用while迭代器遍历集合和增强for循环遍历集合
     */
    public static void main(String[] args ){
    
    
        Collection<String> c = new ArrayList<>();
        c.add("王虎");//添加数据
        c.add("刘华");
        c.add("黄花");

        System.out.println(c.size());//返回集合的个数
        System.out.println(c.isEmpty());//判断集合是否为空
        System.out.println(c.contains("刘华"));//判断集合是否包含"刘华"
        System.out.println(c.remove("刘华"));//删除刘华
        System.out.println(c.size());

        Iterator<String> is = c.iterator();//调用接口的实现类
        while (is.hasNext()){
    
    //判断集合中有无数据
            String em = is.next();//将数据取出,并移到下一个数据上
            System.out.println(em);
        }
        c.clear();//清除集合数据,但不是删除集合
        System.out.println(c);

        test01();//调用方法
        test02();

    }
    private static void test02(){
    
    

        ArrayList<String> em = new ArrayList<>();
        em.add("花花");
        em.add("呼呼");
        em.add("黄乎乎");
        for (String i:em) {
    
    
            System.out.println(i);
        }
    }
    private static void test01(){
    
    

        int[] arr = {
    
    1,2,3,4,5};//建立int数组
        for (int i : arr) {
    
    //for增强循环
            System.out.print(" "+i);
        }
        System.out.println();
    }
}

集合实例–斗地主

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述代码如下:

package cn.gather;

import java.util.ArrayList;
import java.util.Collections;

/**
 * 斗地主案例
 * 1.准备牌
 * 2.洗牌
 * 3.发牌
 * 4.看牌
 */
public class DouDiZhu {
    
    
    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 color:colors) {
    
    
            for (String number:numbers) {
    
    
                poker.add(color+number);
            }
        }
        //System.out.println(poker);

        /**
         * 2.洗牌
         * 使用集合工具类Collection中的方法
         * static void shuffle(list<?> list)使用默认的方法进行乱序存放
         */
        Collections.shuffle(poker);
        //System.out.println(poker);

        /**
         * 3.发牌
         */
        //定义四个集合,分别是存放三个人的牌和底牌
        ArrayList<String> player01 = new ArrayList<>();
        ArrayList<String> player02 = new ArrayList<>();
        ArrayList<String> player03 = new ArrayList<>();
        ArrayList<String> dipai = new ArrayList<>();
        /**
         * 遍历集合获取每一张牌
         * 然后根据i模除3等于多少发到对应人的手里
         * 如果i>=51,则把最后三张发给底牌,因为是从0开始的所以是51而不是52,一共是到53
         */
        for (int i = 0; i < poker.size(); i++) {
    
    
            String s = poker.get(i);
            if (i>=51){
    
    
                dipai.add(s);
            }else if (i%3==0){
    
    
                player01.add(s);
            }else if (i%3==1){
    
    
                player02.add(s);
            }else if (i%3==2){
    
    
                player03.add(s);
            }
        }

        /**
         * 4.看牌
         */
        System.out.println(player01);
        System.out.println(player02);
        System.out.println(player03);
        System.out.println(dipai);
    }
}

在这里插入图片描述

数组的特点

在这里插入图片描述

数组和集合的区别

在这里插入图片描述

数组长度固定,集合长度不固定。数组类型固定,集合类型不固定。数组查找效率高,因为他的地址是连续的,通过索引可以快速找到某一个元素,但是数组的增删是效率极低的,因为其长度固定,所以增删的时候需要新建一个数组然后将原数组内容复制过来。
链表查询慢,增删快与数组刚好相反:,单链表是上个节点记得下个节点的地址,但下个节点记不住上个节点的地址,所以单向。增删元素只需改变节点的自身地址和下一个的地址即可。

树形结构,红黑树查询速度非常之快:

在这里插入图片描述

List集合

关于List集合为什么是“List list = new ArrayList();”定义而不是"Collection list = new ArrayList<>();"这样定义,原因是因为多态,后者运用了多态机制,无法调用ArrayList自身的方法和属性,还有就是List和Set集合的共同特点形成了Collection接口,Collection接口没有带索引的方法,List有带索引的方法。
在这里插入图片描述

List接口中的ArrayList接口适合查找,因为ArrayList是基于数组的操作,带有索引,不适合增删。LinKedList接口是基于链表的,适合增删,每次查找都从头开始,查找效率极低,当然还有更快的查询方式,在这里只是相比而言。

//三种遍历数组的方法********************
//for遍历
for (int i = 0; i < list.size(); i++) {
    
    
    String s1 = list.get(i);
    System.out.println(s1);
}
System.out.println("--------------");
//迭代器遍历
Iterator<String> it = list.iterator();
while (it.hasNext()){
    
    
    String em = it.next();
    System.out.println(em);
}
System.out.println("--------------");
//增强for遍历
for (String i :list) {
    
    
    System.out.println(i);
}

LinkedList集合

在这里插入图片描述

Set集合

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

package cn.gather;

import java.util.*;

/**
 * List集合:具有索引,可以有重复的数据,可以使用任何方式遍历结果。
 * Set集合:没有索引,也没有带有索引的方法,不能使用普通的for循环遍历,也不能有重复的数据
 */
public class DemoList {
    
    
    public static void main(String[] args ){
    
    
        //arraylist();
        //linkedlist();
          hashset();
    }

    /**
     *HashSet特点:
     * 1.不允许重复
     * 2.没有索引,也没有带索引的方法
     * 3.是一个无序的集合,也就是插入和输出的顺序不一致
     * 4,底层实现是一个哈希表,哈希表查询的速度非常快
     */
    private static void hashset() {
    
    
        HashSet<Integer> set = new HashSet<>();
        //使用.add方法插入数据到哈希表中,add方法是Collection继承给Set接口的
        set.add(1);
        set.add(2);
        set.add(3);
        set.add(1);
        //使用迭代器遍历
        Iterator<Integer> it = set.iterator();
        while (it.hasNext()){
    
    
            Integer em = it.next();
            System.out.println(em);
        }
        System.out.println("--------------");
        //使用增强for循环遍历
        for (Integer i : set) {
    
    
            System.out.println(i);
        }

    }

    /**
     *LinkedList集合,是基于链表的集合,适合增删,都有带有索引的方法
     */
    private static void linkedlist() {
    
    
        LinkedList<String> link = new LinkedList<>();
        link.push("a");
        link.addFirst("a");
        link.add("b");
        //System.out.println(link.removeFirst());
        System.out.println(link.removeFirst());
        System.out.println(link.pop());
        System.out.println(link.getFirst());
        System.out.println(link);


    }

    /**
     *ArrayList集合是基于数组产生的,具有索引,常用作查找功能
     */
    private  static void arraylist(){
    
    
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("a");
        System.out.println(list);

        list.add(3,"2");
        System.out.println(list);
        String s = list.get(2);
        System.out.println(s);
        list.remove(1);
        list.set(2,"d");
        System.out.println(list);
        System.out.println("--------------");
        //for遍历
        for (int i = 0; i < list.size(); i++) {
    
    
            String s1 = list.get(i);
            System.out.println(s1);
        }
        System.out.println("--------------");
        //迭代器遍历
        Iterator<String> it = list.iterator();
        while (it.hasNext()){
    
    
            String em = it.next();
            System.out.println(em);
        }
        System.out.println("--------------");
        //增强for遍历
        for (String i :list) {
    
    
            System.out.println(i);
        }
    }
}

哈希表对于没有定义的数据类型如User、Student必须重写Hashcode和equals方法

package cn.gather;

import java.util.*;

/**
 * List集合:具有索引,可以有重复的数据,可以使用任何方式遍历结果。
 * Set集合:没有索引,也没有带有索引的方法,不能使用普通的for循环遍历,也不能有重复的数据
 */
public class DemoList {
    
    
    public static void main(String[] args ){
    
    
        //arraylist();
        //linkedlist();
        //hashset();

       /* HashSet<Person> set = new HashSet<>();//哈希表对于没有定义的数据类型需要重写Hashcode和equals方法
        Person p1 = new Person("刘哥" ,23);
        Person p2 = new Person("刘哥" ,23);
        Person p3 = new Person("海哥" ,28);
        set.add(p1);
        set.add(p2);
        set.add(p3);
        System.out.println(set);*/
        add(1,2,3,4,5,6);
        mand(1,2,3,4,5,"sd","das",23);

    }

    private static  void mand(Object...arr){
    
    
        System.out.println(arr);
        for (int i = 0; i < arr.length; i++) {
    
    
            System.out.println(arr[i]);
        }
    }
    private  static int add(int...arr){
    
    
        System.out.println(arr);
        System.out.println(arr.length);
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
    
    
            sum = sum + arr[i];
        }
        System.out.println(sum);
        return 0;
    }

    /**
     *HashSet特点:
     * 1.不允许重复
     * 2.没有索引,也没有带索引的方法
     * 3.是一个无序的集合,也就是插入和输出的顺序不一致
     * 4,底层实现是一个哈希表,哈希表查询的速度非常快
     */
    private static void hashset() {
    
    
        HashSet<Integer> set = new HashSet<>();
        //使用.add方法插入数据到哈希表中,add方法是Collection继承给Set接口的
        set.add(1);
        set.add(2);
        set.add(3);
        set.add(1);
        //使用迭代器遍历
        Iterator<Integer> it = set.iterator();
        while (it.hasNext()){
    
    
            Integer em = it.next();
            System.out.println(em);
        }
        System.out.println("--------------");
        //使用增强for循环遍历
        for (Integer i : set) {
    
    
            System.out.println(i);
        }

    }

    /**
     *LinkedList集合,是基于链表的集合,适合增删,都有带有索引的方法
     */
    private static void linkedlist() {
    
    
        LinkedList<String> link = new LinkedList<>();
        link.push("a");
        link.addFirst("a");
        link.add("b");
        //System.out.println(link.removeFirst());
        System.out.println(link.removeFirst());
        System.out.println(link.pop());
        System.out.println(link.getFirst());
        System.out.println(link);


    }

    /**
     *ArrayList集合是基于数组产生的,具有索引,常用作查找功能
     */
    private  static void arraylist(){
    
    
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("a");
        System.out.println(list);

        list.add(3,"2");
        System.out.println(list);
        String s = list.get(2);
        System.out.println(s);
        list.remove(1);
        list.set(2,"d");
        System.out.println(list);
        System.out.println("--------------");
        //for遍历
        for (int i = 0; i < list.size(); i++) {
    
    
            String s1 = list.get(i);
            System.out.println(s1);
        }
        System.out.println("--------------");
        //迭代器遍历
        Iterator<String> it = list.iterator();
        while (it.hasNext()){
    
    
            String em = it.next();
            System.out.println(em);
        }
        System.out.println("--------------");
        //增强for遍历
        for (String i :list) {
    
    
            System.out.println(i);
        }
    }
}

可变参数:
在这里插入图片描述

//在集合中添加多个元素,并将其打乱
ArrayList<String> list01 = new ArrayList<>();
//在集合中添加多个元素 addall()
Collections.addAll(list,"1","a","heihua","b","df");
Collections.shuffle(list);

ArrayList<Integer> list01 = new ArrayList<>();
Collections.addAll(list01,1,2,3,3,2,7,4,5);
Collections.sort(list01);
System.out.println(list01);

ArrayList<String> list02 = new ArrayList<>();
Collections.addAll(list02,"c","g","a","me");
Collections.sort(list02);
System.out.println(list02);

ArrayList<Person> list03 = new ArrayList<>();//自己定义的类并没有重写Comp..。。方法
list03.add(new Person("张三",35));
list03.add(new Person("赵六",10));
list03.add(new Person("五把",33));
Collections.sort(list03);
System.out.println(list03);

********************************
//自己定义的类没有默认的排序,需要重写CompareTo方法
/*
重写CompareTo方法
更改排序规则
 */
@Override
public int compareTo(Person o) {
    
    
    //自定义排序规则,比较年龄排序
    return this.Age - o.Age;//升序
}

比较器

在这里插入图片描述

Map

在这里插入图片描述

HashSet和TreeSet比较

如果需要排序就用TreeSet,如果不需要比较就用HashSet。HashMap的运行速度比较快,如果不需要按照排序的话还是推荐HashMap。
在这里插入图片描述

Map接口中的常用方法

在这里插入图片描述

//Map集合迭代必须先转换成set集合再进行迭代
HashMap<String,String> map = new HashMap<>();
map.put("张飞","张翼德");
map.put("刘备","刘玄德");
map.put("曹操","曹孟德");
map.put("赵云","赵子龙");
map.put("周瑜","周公瑾");

// System.out.println(map.remove("张飞"));
System.out.println(map);
//System.out.println(map.get("关羽"));
//System.out.println(map.containsKey("关羽"));
**********************
//第一种遍历方法
Set<String> set = map.keySet();
for (String i : set) {
    
    
    String s = map.get(i);
    System.out.println(i+"="+s);
}
**********************
//第二种遍历方法
Set<Map.Entry<String, String>> set = map.entrySet();
for (Map.Entry i : set) {
    
    
    System.out.println(i.getKey() + "=" + i.getValue());
}

关于Map集合存入Student的时候,如果key是Student那么student类必须重写equals和hashcode方法,如果key是String类则不用,这和上面的一个道理,如果自己定义的类牵扯到重复值的问题,那么久必须重写equals和hashcode方法。
代码如下:

//String类型做Key的值,不需要重写,Java自带
HashMap<String,Student> map = new HashMap<>();
map.put("张飞",new Student("张翼德",35));
map.put("孙权",new Student("孙仲谋",35));
map.put("袁绍",new Student("袁本初",35));
map.put("张飞",new Student("张",35));
//Student类做Key的值,必须重写方法
HashMap<Student,String> map = new HashMap<>();
map.put(new Student("张飞",23),"张翼德");
map.put(new Student("马超",23),"马孟起");
map.put(new Student("鲁肃",23),"鲁子敬");
map.put(new Student("张飞",23),"张");
//利用增强for循环来遍历HashMap集合
for (Map.Entry i:
     map.entrySet()) {
    
    
    System.out.println(i.getKey() + "=" + i.getValue());
}

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

package cn.gather;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 *计算字符串中每个字符出现的次数
 * 1.使用Scanner获取字符
 * 2.创建map集合,key是字符串中的字符,value是字符出现的次数
 * 3.通过字符串遍历,取出每一个元素
 * 4.使用获取到得字符与map集合中的key判断有没有
 * 5.key如果存在,在获取value,value++,不存在put方法,添加key和value,value=1;
 * 6.遍历map集合输出结果
 */
public class DenoMapTest {
    
    
    public static void main(String[] args ){
    
    
        //输入一个字符串
        Scanner input = new Scanner(System.in);
        System.out.println("请输入一个集合:");
        String x = input.next();
        //建立Map集合
        HashMap<Character,Integer> map = new HashMap<>();
        //先将输入的字符串转化成一个字符串数组对数组进行遍历,与集合中的key进行比较,有的话value加一,没有的话用put存入
        for (char i: x.toCharArray()) {
    
    
            if (map.containsKey(i)){
    
    
                Integer d = map.get(i);
                d++;
                map.put(i,d);
            }else {
    
    
                map.put(i,1);
            }
        }
        //Map集合不能直接迭代,需要转化一下,我这里用了entryset类进行遍历
        for (Map.Entry i:
             map.entrySet()) {
    
    
            System.out.println(i.getKey() + "=" + i.getValue());
        }
    }
}

在这里插入图片描述

斗地主综合案例升级版(添加看牌时排序功能)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码如下:

package cn.gather;

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

/**
 * 斗地主综合案例升级版(实现了看牌时排序功能)
 * 1.准备牌
 * 2.洗牌
 * 3.发牌
 * 4.看牌
 */
public class DouDiZhuT {
    
    
    public static void main(String[] args ){
    
    
        /**
         * 1.准备牌
         */
        //先建立两个数组用来存放花色和数字,然后再对他们进行合并,插入Map数组
        String[] colors ={
    
    "♥","♣","♦","♠"};
        String[] numbers = {
    
    "2","A","K","Q","J","10","9","8","7","6","5","4","3"};
        //建立一个Map数组,先存放大王和小王
        HashMap<Integer,String> map = new HashMap<>();
        //创建List集合对扑克牌进行洗牌,List集合里面放的是Map集合的索引
        ArrayList<Integer> list = new ArrayList<>();
        map.put(0,"大王");
        map.put(1,"小王");
        list.add(0);
        list.add(1);
        Integer k = 2;
        for (String i : numbers) {
    
    
            for (String j : colors) {
    
    
                map.put(k,j+i);
                list.add(k);
                k = k +1;
            }
        }
        //System.out.println(map);
        //System.out.println(list);
        /**
         * 2.洗牌
         */
        //对List集合进行乱序
        Collections.shuffle(list);
        //System.out.println(list);
        /**
         * 3.发牌
         */
        ArrayList<Integer> player01 = new ArrayList<>();
        ArrayList<Integer> player02 = new ArrayList<>();
        ArrayList<Integer> player03 = new ArrayList<>();
        ArrayList<Integer> dipai    = new ArrayList<>();

        //遍历List集合
        for (int i = 0; i < list.size(); i++) {
    
    
            Integer s = list.get(i);
            if (i>=51){
    
    
                dipai.add(s);
            }else if (i%3==0){
    
    
                player01.add(s);
            }else if(i%3==1){
    
    
                player02.add(s);
            }else if(i%3==2){
    
    
                player03.add(s);
            }
        }
        //排序
        Collections.sort(player01);
        Collections.sort(player02);
        Collections.sort(player03);
        Collections.sort(dipai);

        /**
         * 4.看牌
         */
        lookpoker("云长",map,player01);
        lookpoker("翼德",map,player02);
        lookpoker("玄德",map,player03);
        lookpoker("底牌",map,dipai);

    }

    /**
     *建立看牌的方法
     * @param name : 玩家姓名
     * @param map :存放扑克牌的Map集合
     * @param list :存放索引的List集合
     */
    public  static  void lookpoker(String name,HashMap<Integer,String> map,ArrayList<Integer> list){
    
    
        //输出姓名
        System.out.print(name + ": ");
        //遍历玩家或者底牌集合,获取索引
        for (Integer key : list) {
    
    
            String value = map.get(key);
            System.out.print(value + " ");
        }
        System.out.println();
    }
}

结果:
在这里插入图片描述

彩蛋

此篇博客大都是我的笔记所写,包含一些我学集合的截图与代码,如有需要评论或私我要原版笔记~ 关于泛型的笔记链接点这里–>(笔记链接),自取~ 谢谢捧场~

猜你喜欢

转载自blog.csdn.net/weixin_44475741/article/details/109520335