java基础2.5(集合)

java基础第二阶段之day5

一、集合分类

  • 集合类体系结构图:

在这里插入图片描述

二、Collection集合

1. Collection介绍

Collection集合,它是单列集合,创建Colection集合的对象要用多太的方式(ArrarList();)

多态的方式创建Collection对象:
    //Collection<E> 
    Collection<String>  c = new ArrayList<String>();
	//用Collection的 boolean add<E e> 方法往集合添加元素
	c.add("hello");
	c.add("world");
	c.add("java");
	system.out.println(c);
//此处结果为:
[hello,world,java]

可以看出,ArrayList里是自动重写了父类的toString方法的,所以输出的是[元素1,元素2...,元素n]的格式
而不是 对象名+@+哈希值 格式(这个格式是没有重写的)。

2. Collection的常用集合方法:

在这里插入图片描述

boolean add(E e) 底层代码返回的返回值定义的就是ture,所以使用add永远返回的都是ture。

boolean remove(object o )移除成功返回ture,失败返回false。

void clear() 是直接清空集合里的元素,需要谨慎使用。

boolean isEmpty() 是判断集合是否为空,ture是表示为空,false是表示不为空。

3. Collection的iterator()方法

Iterator iterator()是方法是返回此集合中元素的迭代器

所以可以通过iterator()方法创建一个该集合的一个迭代器。然后通过迭代器对象对该集合的数据进行操作。


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

public class CollectionDemo1 {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<String>();
        c.add("hello");
        c.add("world");
        c.add("java");
   //     System.out.println(c.remove("java")); 移除某个元素的方法
   //     c.clear();清空
   //     System.out.println(c.contains("java")); 判断集合是否有指定元素  结果:返回ture;
   //    System.out.println(c.isEmpty()); 判断是否为空,结果:false
   //    System.out.println(  c.size()); 集合的大小,结果:3
        
        System.out.println(c);
        //Iterator()方法
        Iterator<String> it = c.iterator();//通过集合迭代器iterator遍历对象
       while (it.hasNext()){                //不用for循环遍历是因为迭代器是一个个接收数据的
           String s = it.next();            //没有办法知道共有多少个元素,所以没有it的大小,也就没办法通过index遍历了
           System.out.println(s);           //这里是通过hasNext判断是否仍有下一个判断it的结束点。
       }

    }
}
这里用到了迭代器两个常用方法:
    1. 	E next();返回迭代中的下一个元素
	2.	boolean hasNext();如果迭代具有更多元素,则返回ture


总结Collection集合使用步骤:
在这里插入图片描述

三、List集合

1. List概述和特点

在这里插入图片描述

代码演示:

在这里插入图片描述

基本功能和Collection一致,此外List还有它特有的方法:
在这里插入图片描述

注意:

以上所有方法都会出现索引越界异常,使用的时候注意索引在有效范围内。

删除和修改方法返回的都是未更改前索引位置的元素。

因为List可以通过访问索引来获取元素,于是要遍历List集合除了可以使用迭代器外,还可以通过for循环完成遍历。

但是注意利用迭代器进行遍历的时候不能同时对集合长度进行修改,不然会出现并发修改异常

ConcurrentModificationException

2. 实际应用例子(并发修改异常)


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

public class ListDemo1 {
    public static void main(String[] args) {
        //创建LIist对象
        List<String> l =  new ArrayList<>();
        //添加元素
        l.add("hello");
        l.add("java");
        l.add("javaee");

        //遍历集合,遍历要求:遍历的过程如果有java,则添加一个”world“
        //1.迭代器遍历(无法实现)
        Iterator<String> it = l.iterator();
        while (it.hasNext()){
            String s = it.next();
            if (s.equals("java")){
                l.add("world");     //ConcurrentModificationException
                                    //并发修改异常
            }                       //利用迭代器遍历的时候,不可以遍历的同时改变集合的长度
            System.out.println(s);

        }

        //2.利用索引for循环遍历
        for (int i = 0; i < l.size(); i++) {
            String s = l.get(i);
            if (s.equals("java")){
                l.add("world");
            }
            System.out.println(s);

        }
    }
}

3. List特有迭代器

在这里插入图片描述


import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ListIteratorDemo1 {
    public static void main(String[] args) {
        List<String> l = new ArrayList<>();

        l.add("java");
        l.add("c++");
        l.add("python");

        ListIterator<String> lit = l.listIterator();
        while (lit.hasNext()){
            String s1 = lit.next();//顺序遍历
            System.out.print(s1+"\t");

        }
        System.out.println();
        System.out.println("-------------------------");
        while (lit.hasPrevious()){
            String s2 = lit.previous();//逆序遍历
            System.out.print(s2+"\t");
        }
        System.out.println();
        System.out.println("-------------------------");
        //利用迭代器遍历,若出现java字符串则加上PHP。
        while (lit.hasNext()){
            String s = lit.next();
            if(s.equals("java")){
                lit.add("PHP"); //注意:这个add方法是迭代器的方法,不是集合的方法
            }
            System.out.print(s+"\t");//此时是添加了PHP元素到列表集合但是遍历依旧不会遍历这个中途加入的。
        }
        System.out.println();
        System.out.println(l);//此时的列表集合已经有PHP元素。
    }
}

4. for-each遍历集合原理

首先回顾for-each循环遍历的基本格式:

for(元素数据类型 变量名:数组或者Collection集合){

//此处使用变量进行操作,此处的变量就是各元素;

}
Collection<String> c = new ArrayList<String>();
        c.add("hello");
        c.add("world");
        c.add("java");

   for (String s1:c) {     //foreach原理其实就是通过迭代器用next方法把各个元素取出,
                                // 赋值给foreach里定义的变量,然后通过循环把所有的元素遍历出来
            System.out.println(s1);
        }

可以通过在遍历的同时修改集合长度,若抛出并发修改异常,即可证明foreach是利用iterator迭代器。
    for(String s2:c){
        if(c.equals("java")){
            c.add("c++") 	//此处抛出并发修改异常 ConcurrentModificationException
        }
    }

得出结论,Collection及其子类都应该具有两个或以上的遍历方法

1.迭代器遍历

2.增强for遍历

3.fori循环(List特有,利用索引)

5. 常用数据结构之栈,队列,数组,链表

1.栈

在这里插入图片描述

入栈过程:

入栈顺序元素名
03C
02B
01A

栈的特点是先进后出,A是第一个进来的,但是A要出来的时候,A就是最后一个出来了

出栈过程

出栈顺序元素名
01C
02B
03A

2.队列

在这里插入图片描述

入队顺序元素名
03C
02B
01A

队列的特点是先进先出,就是A是先进来的,所以先出来的时候,A也是第一个出来的。

出队顺序元素名
03C
02B
01A

3.数组(Array)

在这里插入图片描述

特点:查询的速度快(通过索引,搜索哪个的速度都是一样的)

​ 增删的速度慢 (牵一发而动全身)


4.链表(Linked)

在这里插入图片描述

特点:增删速度相较于数组快(修改上一元素地址值和自身地址值即可完成增删)

​ 查询速度相较于数组慢(每一次查询都必须从头部出发去查询)

6. 两种数据结构的List集合实现类

根据两种数据结构的不同,自然而然就产生了两种数据结构的实现类:

ArrayList(数组类型)和LinkedList(链表类型)


  • ArrayList(数组类型)实现类:

使用方法就是

ArrayList list = new ArrayList();

前面的例子都是通过这个实现类进行演示的,

简单的说就是get,set,add,remove方法。

ArrayList的基本方法


  • LinkedList (链表类型)的实现类:

LinkedList list = new LinkedList();

他有他特有的对数据的处理方法:

在这里插入图片描述

import java.util.LinkedList;

public class LinkedListDemo1 {
    public static void main(String[] args) {
        LinkedList<String> l1 =new LinkedList<>();
        l1.add("java");
        l1.add("c++");
        l1.add("python");

        l1.addFirst("hello");//在最开始添加一个元素
        l1.addLast("ok");//addLast() = add() 在列表最后添加元素

        System.out.println(l1);

        System.out.println( l1.getFirst());//获得开头的元素
        System.out.println(l1.getLast());//获得最后的元素

        System.out.println(l1.removeFirst());//删除列表开始的元素并把他返回
        System.out.println(l1.removeLast());//删除列表开始的元素并把他返回
        System.out.println(l1);

    }
}
/*
结果:

[hello, java, c++, python, ok]
hello
ok
hello
ok
[java, c++, python]

 */

四、Set集合

1. Set集合概述

  • set是继承自Collection的所以有collection的所有特点

  • set独有的特点是,元素不能重复;

  • 没有索引,无法使用fori循环遍历

在这里插入图片描述


2. HashSet

在这里插入图片描述


import com.lys.oop.extendsDemo.Students;
import com.sun.xml.internal.ws.encoding.HasEncoding;

import java.util.HashSet;

public class HashSetDemo1 {
    public static void main(String[] args) {
        HashSet<String> hs1 = new HashSet<>();
        String s1 = "java";//96515
        String s2 = "c++";//3254818
        String s3 = "c";//99
        String s4 = "c";
        hs1.add(s1);
        hs1.add(s2);
        hs1.add(s3);
        hs1.add(s4);//字符串相同,在堆里是同一个,所以是一致的,不重复添加
        for (String s :hs1) {
            System.out.println(s+"\t"+s.hashCode());
        }
        HashSet<Students> hs2 = new HashSet<>();
        Students stu1 = new Students("java",18);
        Students stu2 = new Students("c++",18);
        Students stu3 = new Students("java",18);
    //注意,这里的stu1=stu3,但是却两个都能输出,原因是因为在栈堆中,创建的对象不一样。
        //解决方案,去对象的源码,重写hashcode和equlas方法
        hs2.add(stu1);
        hs2.add(stu2);
        hs2.add(stu3);
        System.out.println(hs2);
    }
}

保证元素唯一性的源码分析:

在这里插入图片描述

为什么hashset的元素不重复?

HashSet<String> hs = new HashSet<>();
hs.add("java");//96515
hs.add("c++");//3254818
hs.add("c");//99
hs.add("c");//99       //是因为添加元素的时候,重复值被处理了,所以看add方法

根据API把所有相关源码展示:

public boolean add(E e) {       //add方法用到了put方法,e表示我放进去的对象,这里用”java“表示
return map.put(e, PRESENT)==null;
}


public V put(K key, V value) {        //key就是java。这里对我的”java“字符串进行了hashcode方法。java.hashcode()=96515
return putVal(hash(key), key, value, false, true);   //把96515和”java“作为参数传到putVal()中;
}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {
    Node<K,V>[] tab;   //tab是一个数组,由”java“这样的对象+一个值构成,这个值是上面的PRESENT
    Node<K,V> p;       //p是一个对象,由”java“这样的对象+一个值构成,这个值是上面的PRESENT
    int n, i;

存入的元素和以前的元素比较哈希值
    如果哈希值不一样,继续执行,把元素添加到集合
    如果是一样的,调用对象的equals方法比较
        如果返回false,继续执行,添加到集合
        如果返回ture,说明元素重复,不存储

    if ((tab = table) == null || (n = tab.length) == 0) //如果这个表是等于初始表的,或者这个表长度为空的
        n = (tab = resize()).length;    //初始化这个哈希表

    if ((p = tab[i = (n - 1) & hash]) == null)      根据这个hash值判断对应存储空间是否为空
        tab[i] = newNode(hash, key, value, null);   //把 p对象初始化并把它写进表的第i号位
    else {
        Node<K,V> e; K k;
        if (p.hash == hash &&       //存入的hash值和原来的hash值比较
            ((k = p.key) == key || (key != null && key.equals(k))))     对象是不是和原来的一样 || 再通过对象的equals方法再判断一次是否一样
            e = p;      //把这个新的对象赋值给原来的对象。(但是其实是一样的)
        else if (p instanceof TreeNode)
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else {
            for (int binCount = 0; ; ++binCount) {
                if ((e = p.next) == null) {
                    p.next = newNode(hash, key, value, null);
                    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                        treeifyBin(tab, hash);
                    break;
                }
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    break;
                p = e;
            }
        }
        if (e != null) { // existing mapping for key
            V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e);
            return oldValue;
        }
    }
    ++modCount;
    if (++size > threshold)
        resize();
    afterNodeInsertion(evict);
    return null;
}

逻辑图法:

在这里插入图片描述

3. 常用数据结构之哈希表

在这里插入图片描述

哈希表是采用数组加链表的形式存储的,

1.把对象的hashcode算出来

2.把hashcode全部取余16

3.算出一个常数。该常数就是数组的索引位置

4.然后就把对象一个个放入数组

5.当常数一致时(就是说该位置已经有对象了,但是我后面还有是属于这个位置的对象进来),

比较两个对象的hashcode,不一致则在该对象后面以链表的数据类型存储,

若一致,再次比较两个对象的内容,两者内容一样,则说明元素一致,不存储。

若不一致,则在这对象后面用链表的形式存储。

在这里插入图片描述

4.LinkedHashSet集合的概述和特点

在这里插入图片描述

代码演示

import java.util.LinkedHashSet;
//LinkedHashSet特点:因为Linked存储数据,元素有序
                        //hash表存储,元素不重复
public class LinkedHashSetDemo1 {
    public static void main(String[] args) {
        LinkedHashSet<String> lhs=new LinkedHashSet<>();
        String s1 = "java";
        String s2 = "c";
        String s3 = "c++";
        String s4 = "java";
        lhs.add(s1);
        lhs.add(s2);
        lhs.add(s3);
        lhs.add(s4);

        for (String s:lhs) {
            System.out.println(s);
        }

    }
}
/*
结果:

java
c
c++

*/

5.TreeSet

特点:

  • public class TreeSet<E>
    	extends AbstractSet<E>
    		implements NavigableSet<E>, Cloneable, Serializable
    		
    

    NavigableSet实现基于TreeMap 的元件使用其有序natural ordering ,或由Comparator集合创建时提供,这取决于所使用的构造方法。

在这里插入图片描述

代码演示:

要求:1.TreeSet集合存储学生对象并遍历,创建集合的无参构造
    2.按照年龄大小顺序排序,若年龄相同,则按姓名的字母顺序排列
    
    思路:1.创建student类,并在测试类引入对象
    	2.测试类引入集合,把学生对象添加到集合里,并遍历
    	3.由于用TreeSet集合,故集合的泛型对象必须实现Comparable<T>的接口
    	4.重写实现类的compareTo()方法,根据返回值的特性完成对元素的顺序排列
------------------------------------------
public class StudentPo implements Comparable<StudentPo> {

    int age;
    String name;


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


    public StudentPo() {
    }

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


    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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


    @Override
    public int compareTo(StudentPo s) {
        //   return 0; //不进行比较
        //    return 1;      //顺序比较
        //  return -1;   //逆序排列
        int num1 = 0;
        if (this.age - s.age != 0) {
            num1 = this.age - s.age;
        } else {
            num1 = this.name.compareTo(s.name) ;
        }
        return num1;
    }
}
---------------------------------------------------------------------------------
import java.util.TreeSet;

/*TreeSet特点:
1.继承Set元素不重复
2.有一定规律的顺序,自然顺序
*/
public class TreeSetDemo1 {

    public static void main(String[] args) {
        //创建集合对象
        TreeSet<StudentPo> ts1 = new TreeSet<>();
        //创建学生对象
        StudentPo stu1 =new StudentPo( 16,"sting" );
        StudentPo stu2 =new StudentPo( 16,"char" );
        StudentPo stu3 =new StudentPo( 30,"int" );
        StudentPo stu4 =new StudentPo( 50,"varchar" );

        StudentPo stu5 =new StudentPo( 16,"sting" );//相同的项,根据特性不输出相同的元素

        ts1.add(stu1);
        ts1.add(stu2);
        ts1.add(stu3);
        ts1.add(stu4);
        ts1.add(stu5);



        for (StudentPo i:ts1) {
            System.out.println("[name:"+i.getName()+"\t"+"age:"+ i.getAge()+"]");
        }

    }

}

/*
结果:

[name:char	age:16]
[name:sting	age:16]
[name:int	age:30]
[name:varchar	age:50]

*/

------------------------------------------------------------
    而利用有参构造完成这个问题则不需要让student对象实现comprable接口,然后重写它的compareTo方法
    而是直接在new TreeSet集合对象的时候,通过匿名内部类的办法重写comparator的compare方法就完事了
    核心代码如下:
    
     TreeSet<StudentPo> ts2 = new TreeSet<>(new Comparator<StudentPo>() {
            @Override
            public int compare(StudentPo s1, StudentPo s2) {
                int num1 = 0;
                if (s1.getAge() - s2.getAge() != 0) {
                    num1 = s1.getAge() - s2.getAge();
                } else {
                    num1 = s1.getName().compareTo(s2.getName()) ;
                }
                return num1;
            }
        });

结论:

在这里插入图片描述

实战例子:产生10个不重复的随机数

package com.lys.heima.javaSEjichu;

import java.util.HashSet;
import java.util.Random;
import java.util.Set;
//要求:写一个程序,获取1-20的10个随机整数,要求10个整数不重复,把其输出;
//思路:1.随机数用random对象,生成随机数
//     2.通过set集合存储数据,达到随机数不重复,利用循环添加随机数当集合Size=10则停下来
//     3.遍历集合
public class canshen10geshuijishu {
    public static void main(String[] args) {
        Set<Integer> s = new HashSet<>();//此处利用TreeSet作为多态方法的话还能把随机数进行排序
        Random r = new Random();
        while (s.size()<10){
            Integer a =r.nextInt(20)+1;
            s.add(a);
        }

        for (Integer x: s) {
            System.out.println(x);
        }
        System.out.println("size="+s.size());
    }
}

五、泛型

1.泛型介绍:

简单来说:泛型的引入就是减少重复性代码,把相同的行为的代码抽象出来,通过泛型的概念,把这个行为抽象成一类通用行为,只要是符合这个行为的动作,我都可以通过这个泛型定义的行为完成。

在这里插入图片描述

在这里插入图片描述

:常用来表示类型

:常用来表示元素

:常用来表示键

:常用来表示值

泛型类:

格式:修饰符 class 类名<类型>{ }

例子:public class fun<T>{ }

好处:类的成员变量可以在创建对象的时候再去指定;


泛型方法:

格式:修饰符 <类型> 返回值类型 方法名 (类型 变量名){ }

例子:public <T> class fun(T t){ }

好处:方法的参数可以是任意类型,不需写多次的不同参数类型的方法重写,但是相对的代码的安全性需要自己注意,因为无限制,所以报错提示也相对变弱了


泛型接口:

格式:修饰符 interface 接口名<类型>{ }

例子:public interface fun<T>{ }

好处: 创建的接口的参数是任意类型,其实现类的参数也是可以是任意类型


2.类型通配符

在这里插入图片描述

<? extends 类型> :既然是extends ,意味着这个通配符是后面类型的子类或者是它本身

<? super 类型> :这个是super,意味着这个通配符表示的是这个类型的父类或者是这个类型本身。

3.可变参数的使用

可变参数,意思是在方法重写的时候,同一种类型的多个参数在方法中被传入,如果按写定的参数则无法实现这个,于是使用 (参数类型…参数名)的方式表示这个参数的长度是可变的。

public <T> void say(T... t){
    System.out.println(t);
}
注意:这个T...t的底层原理是把t按存T[]这样一个集合存作为参数传到方法中的。所以要使用这种T...的格式的话,这个必须是最后的一个参数。
即(int x ,T... t)
public <T> void say(int x ,T... t){  //T...t不能在x前面。
    System.out.println(t);
}

集合上的可变参数的使用:

在这里插入图片描述


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
//注:List。of()和Set.of()方法在jdk9才能使用
public class ListofDemo1 {
    public static void main(String[] args) {
        List<String> l1 = Arrays.asList("java","c++","c");//可以在这添加元素
//        l1.add("a");//UnsupportedOperationException
//        l1.remove("a");//UnsupportedOperationException
        l1.set(1,"a");//可行
        List<String> l2 = List.of("java","c++","c");//可以在这里添加元素
        l2.set(1,"c#");//可行
        l2.add("c#");//UnsupportedOperationException
        l2.remove("c#");//UnsupportedOperationException

       Set<String> set= Set.of("java","c++","c","c");//IllegalArgumentException,元素不可重复
        set.add("c#");//UnsupportedOperationException
        set.remove("c#");//UnsupportedOperationException
    }
}

六、Map

1.概述和特点:

在这里插入图片描述

基本功能:

在这里插入图片描述

代码展示:

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class MapDemo1 {
    public static void main(String[] args) {

        Map<String,String> m =new HashMap<>();//TreeMap<>();多种多态方式
        //put方法添加元素
        m.put("01","java");
        m.put("02","c++");
        m.put("03","c#");
        m.put("04","c#");
        //remove方法删除元素,返回值是K对应的V值;
        System.out.println(m.remove("01"));
        //clear,清空集合
        m.clear();
        //containsKey,和containsValue 对比键和值 ,返回值是boolean类型
        System.out.println(m.containsKey("01"));
        System.out.println(m.containsValue("c++"));
        //size,返回值int型
        System.out.println(m.size());
        System.out.println(m);

    }
}

在这里插入图片描述

以上方法可看出,map集合底层左边的键是以Set集中装的,右边的值是以Collection装的;

        Map<String,String> m =new HashMap<>();
        //put方法添加元素
        m.put("01","java");
        m.put("02","c++");
        m.put("03","c#");
        m.put("04","c#");
//V get(object Key):根据键获取对应的值
        System.out.println(m.get("01"));
//        System.out.println(m.get("05"));//没有则返回null
        //Set<k> keySet();获取所有键的集合
        Set<String> set = m.keySet();
        for (String s:set){
            System.out.print(s+" ");
        }
        System.out.println();
        System.out.println("---------------------");
        //Collection<v> values();获取所有值的集合
        Collection<String> values = m.values();
        for (String s:values){
            System.out.print(s+" ");
        }

2.Map集合的遍历:

方法1:

在这里插入图片描述

//通过键找值      
		Set<String> set = m.keySet();
        for (String s : set){
          String v   = m.get(s);
            System.out.println("key="+s+"\t"+"values="+ v);

方式2:

在这里插入图片描述

Set<Map.Entry<String, String>> entries = m.entrySet();
for ( Map.Entry<String, String> kvd:entries){   //Map.Entry<String, String>键值对对象的类型
    System.out.println(kvd.getKey()+"\t"+kvd.getValue());

3.经典案例

1.在ArrayLIst集合里装HashMap<String,String>类型的数据;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

//在ArrayList集合中存储HashMap类型元素
public class HashMapInstArrayListDemo1 {
    public static void main(String[] args) {
        ArrayList<HashMap<String,String>> arrayList = new ArrayList<>();

        HashMap<String, String> hm1 = new HashMap<String,String>();
        hm1.put("01","java");
        hm1.put("02","c++");

        HashMap<String,String> hm2 = new HashMap<>();
        hm2.put("01","剑姬");
        hm2.put("02","青钢影");

        HashMap<String,String> hm3 = new HashMap<>();
        hm3.put("01","剑魔");
        hm3.put("02","潘森");

        arrayList.add(hm1);
        arrayList.add(hm2);
        arrayList.add(hm3);

        for (HashMap<String,String> hm :arrayList){
            Set<String> keySet = hm.keySet();
            for (String k:keySet){
                String v = hm.get(k);
                System.out.println("k="+k+"\t"+"v="+v);
            }
        }
    }
}
/*
结果:
k=01	v=java
k=02	v=c++
k=01	v=剑姬
k=02	v=青钢影
k=01	v=剑魔
k=02	v=潘森

进程已结束,退出代码为 0

*/
反过来的在idea有案例HashMapInstArrayListDemo2
    

在这里插入图片描述

import java.util.HashMap;
import java.util.Scanner;
import java.util.Set;

//键盘录入一堆字符串,根据字符串出现次数,分处其出现次数
public class HashMapTestdemo1 {
    public static void main(String[] args) {
        //1.键盘录入:
        Scanner sc = new Scanner(System.in);
        String line= sc.nextLine();

        //创建hashmap对象
        HashMap<Character,Integer> hm = new HashMap<>();
		//改进:用TreeMap作为集合来存储可以使结果输出的时候,按照字母的顺序进行排序。
        
        //遍历字符串,化成char类型,然后装箱进集合
        for (int i = 0; i <line.length() ; i++) {
            char key = line.charAt(i);
            //判断返回值,
            //1.若返回值为null,说明集合中没有此字符,则把该字符放进去,并把其值赋为1、
            //2.若返回值为ture,说明已经有此字符,则把其取值出,进行加一操作,再放回集合
                Integer v = hm.get(key);
            if (v==null){
                hm.put(key,1);
            }else {
                v++;
                hm.put(key, v);
            }
        }
        //遍历hashmap集合
        Set<Character> keySet = hm.keySet();
        for(Character k:keySet){
            Integer v = hm.get(k);
            System.out.print(k+"("+v+")");
            //可以通过StringBuilder进行封装,把结果封装起来,存到一个resule里面,方便调用;
           
            /*            StringBuilder sb =new StringBuilder();
            sb.append(k).append("(").append(v).append(")");
            String result = sb.toString();
            System.out.print(result);
  			*/      
        }
    }
}

七、Collections

1.概述

在这里插入图片描述

Collections的方法全是静态方法

使用方法:

Collections.sort(List)	//升序排序
  Collections.reverse(List)//反转元素顺序
    Collections.shuffle(List)//随机排列,每传一次变一次

在这里插入图片描述

使用这个方法进行排序时,必须把传进来的来继承Comparable并重写其方法,或者是在传入数组的时候,同时传入一个Comparator的对象(采用匿名内部类的方法)

2.斗地主模拟案例

package com.lys.heima.javaSEjichu;



import java.util.*;

/*
  要求:实现斗地主的洗牌,发牌和看牌
  思路:
  1.先存牌,用arraylist进行存牌
  2.洗牌。用collections。shuffle()方法把牌打乱
  3.发牌,用Treemap,存对应三个人的名字和牌
  4.看牌,遍历对应的玩家的牌
  */
public class doudizhuDemo1 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        //把花色和字符拼接,添加到集合中
        String[] Color = {"♦", "♣", "♥", "♠"};
        String[] Num = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};

        for (String color : Color) {
            for (String num : Num) {
                arrayList.add(color + num);
            }
        }
        //添加大王小王
        arrayList.add("🧛j");
        arrayList.add("🧛J");
        //System.out.println(arrayList+"\t"+arrayList.size());

        //打乱顺序
        Collections.shuffle(arrayList);
    //    System.out.println(arrayList);
        //发牌,遍历,满17张就换下一个,通过三个数组装载

        //自己想出来的发牌方法
  /*    String[] w1 = new String[17];
        String[] w2 = new String[17];
        String[] w3 = new String[17];
        String[] dz = new String[3];

      for (int i = 0; i <arrayList.size() ; i++) {
            //玩家一
            if (i < 17) {
                w1[i] = arrayList.get(i);

            }
            //玩家二
            else if (17 <= i && i < 34) {
                w2[i - 17] = arrayList.get(i);

            }
            //玩家三
            else if (34 <= i && i < 51) {
                w3[i - 34] = arrayList.get(i);

            }
            //地主牌
            else if (i >= 51 && i < 54) {
                dz[i - 51] = arrayList.get(i);

            }
        }*/
        //老师的方法:
        ArrayList<String> player1 =new  ArrayList<>();
        ArrayList<String> player2 =new  ArrayList<>();
        ArrayList<String> player3 =new  ArrayList<>();
        ArrayList<String> dipai =new  ArrayList<>();


        for (int i = 0; i < arrayList.size(); i++) {
            String pai = arrayList.get(i);
            if (i>=arrayList.size()-3){
                dipai.add(pai);
            }
           else if (i%3==0){
                player1.add(pai);
            }
            else if (i%3==1){
                player2.add(pai);
            }
            else if (i%3==2){
                player3.add(pai);
            }
        }



        StudentPo wj1 = new StudentPo("张三丰",15);
        StudentPo wj2 = new StudentPo("关  羽",17);
        StudentPo wj3 = new StudentPo("王  五",44);
        StudentPo dz = new StudentPo("地主牌",03);
    /*    TreeMap<StudentPo,String[]>  gx= new TreeMap<>();
      gx.put(wj1.w1);
        gx.put(wj2,w2);
        gx.put(wj3,w3);
        gx.put(cp,dz);

        Set<StudentPo> keySet = gx.keySet();
        for (StudentPo k:keySet){
            String[] vsz = gx.get(k);
            System.out.print(k.getName()+"("+k.getAge()+"):");
            for (String v:vsz){
                System.out.print("["+v+"]");
            }
            System.out.println();
        }*/

        lookpoker(wj1,player1);
        lookpoker(wj2,player2);
        lookpoker(wj3,player3);
        lookpoker(dz,dipai);

    }
    public static  void lookpoker(StudentPo s,ArrayList<String> a){
        System.out.print(s.getName()+"("+s.getAge()+"):");
        for(String poker:a) {
            System.out.print(poker+" ");
        }
        System.out.println();
    }

}

3.斗地主模拟升级

在这里插入图片描述

//呜呜呜,敲了两个小时才敲出来的
import java.util.*;

public class doudizhuDemo2 {
    public static void main(String[] args) {
        //1.存牌
        HashMap<Integer, String> paihe = new HashMap<>();

        ArrayList<String> pai = new ArrayList<>();

         String[] Color = {"♦", "♣", "♥", "♠"};
        String[] Num = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
        for (String color : Color) {
            for (String num : Num) {
                pai.add( color + num);
            }
        }
        pai.add("🧛R");
        pai.add("🧛G");
        for (int i = 0; i <54 ; i++) {
             paihe.put(i,pai.get(i));
    }
       Set<Integer> keys = paihe.keySet();
        for (Integer k:keys ){
            String v = paihe.get(k);
            System.out.println(k+":"+v);
        }

        //洗牌
        ArrayList<Integer> xipai = new ArrayList<>();
        for (int i = 0; i < 54; i++) {
            xipai.add(i);
        }
        Collections.shuffle(xipai);
   //     System.out.println(xipai);
        //发牌
        TreeSet<Integer> kd1 = new TreeSet<>();
        TreeSet<Integer> kd2 = new TreeSet<>();
        TreeSet<Integer> kd3 = new TreeSet<>();
        TreeSet<Integer> dipai = new TreeSet<>();

        for (int i = 0; i < xipai.size(); i++) {
            Integer ph = xipai.get(i);
            if (i>=xipai.size()-3){
                dipai.add(ph);
            }
            else if (i%3==0){
                kd1.add(ph);
            }
            else if (i%3==1){
                kd2.add(ph);
            }
            else if (i%3==2){
                kd3.add(ph);
            }
        }
      //  System.out.println(kd3);

        //看牌
        StudentPo wj1 = new StudentPo("张三丰",15);
        StudentPo wj2 = new StudentPo("关  羽",17);
        StudentPo wj3 = new StudentPo("王  五",44);
        StudentPo dz = new StudentPo("地主牌",3);

        see(wj1,kd1,paihe);
        see(wj2,kd2,paihe);
        see(wj3,kd3,paihe);
        see(dz,dipai,paihe);


    }
    public static void see(StudentPo s,TreeSet<Integer> t,HashMap<Integer, String> h){

        System.out.print(s.getName()+"("+s.getAge()+"):");

        for (Integer i:t) {
            String v = h.get(i);
            System.out.print(v+" ");
        }
        System.out.println();

    }

}
/*
结果:

张三丰(15):♦A ♦7 ♦10 ♣3 ♣6 ♣10 ♣Q ♣K ♥A ♥3 ♥4 ♥6 ♥10 ♥Q ♠A 🧛R 🧛G 
关  羽(17):♦2 ♦3 ♦5 ♦6 ♦8 ♦J ♦Q ♦K ♣2 ♣9 ♣J ♥2 ♥5 ♥8 ♥9 ♠6 ♠9 
王  五(44):♦4 ♦9 ♣A ♣4 ♥7 ♥J ♥K ♠2 ♠3 ♠4 ♠5 ♠7 ♠8 ♠10 ♠J ♠Q ♠K 
地主牌(3):♣5 ♣7 ♣8 

进程已结束,退出代码为 0

*/

ze(); i++) {
            Integer ph = xipai.get(i);
            if (i>=xipai.size()-3){
                dipai.add(ph);
            }
            else if (i%3==0){
                kd1.add(ph);
            }
            else if (i%3==1){
                kd2.add(ph);
            }
            else if (i%3==2){
                kd3.add(ph);
            }
        }
      //  System.out.println(kd3);

        //看牌
        StudentPo wj1 = new StudentPo("张三丰",15);
        StudentPo wj2 = new StudentPo("关  羽",17);
        StudentPo wj3 = new StudentPo("王  五",44);
        StudentPo dz = new StudentPo("地主牌",3);

        see(wj1,kd1,paihe);
        see(wj2,kd2,paihe);
        see(wj3,kd3,paihe);
        see(dz,dipai,paihe);


    }
    public static void see(StudentPo s,TreeSet<Integer> t,HashMap<Integer, String> h){

        System.out.print(s.getName()+"("+s.getAge()+"):");

        for (Integer i:t) {
            String v = h.get(i);
            System.out.print(v+" ");
        }
        System.out.println();
    	}
    }
    
/*
结果:

张三丰(15):♦A ♦7 ♦10 ♣3 ♣6 ♣10 ♣Q ♣K ♥A ♥3 ♥4 ♥6 ♥10 ♥Q ♠A 🧛R 🧛G 
关  羽(17):♦2 ♦3 ♦5 ♦6 ♦8 ♦J ♦Q ♦K ♣2 ♣9 ♣J ♥2 ♥5 ♥8 ♥9 ♠6 ♠9 
王  五(44):♦4 ♦9 ♣A ♣4 ♥7 ♥J ♥K ♠2 ♠3 ♠4 ♠5 ♠7 ♠8 ♠10 ♠J ♠Q ♠K 
地主牌(3):♣5 ♣7 ♣8 

进程已结束,退出代码为 0

*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YeungSLee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值