集合

ArrayList:数组存储方式,可以利用索引访问元素。它的优点在于遍历元素和随机访问元素的效率比较高。而且ArrayList存储元素有序,且元素可以重复。

package com.itheima01;

import java.util.ArrayList;

/*

 * 持有数据:

 *      单一数据,可以定义对应类型的变量直接持有

 *      多个数据,可以使用数组的方式记录,通过索引访问数据

 *      又在面向对象的基础上,可以使用集合的方式记录,最开始最常用ArrayList,该集合类同样可以通过索引访问数据

 *

 * 集合的基本使用:

 *      1创建集合对象

 *      2向集合中添加元素

 *      3从集合中获取元素/其他信息(集合的长度)

 */

public class Demo01ArrayList {

 

    public staticvoid main(String[] args) {

       

        //创建集合对象

        ArrayList<Integer>list = newArrayList<Integer>();

        //向集合中添加元素

        list.add(10);

        list.add(100);

        list.add(2000);

        //从集合中获取元素/其他信息(集合的长度)

        Integerinteger = list.get(2);

        System.out.println(integer);

       

        int size = list.size();

        System.out.println(size);

        System.out.println("===============================");

        //遍历集合

        for (inti = 0; i < list.size(); i++) {

            //通过索引依次获取集合中每一个元素

            IntegerthisNumber = list.get(i);

            //打印每个元素

            System.out.println(thisNumber);

        }

    }

}

迭代器概述:

java中提供了很多个集合,它们在存储元素时,采用的存储方式不同。

我们要取出这些集合中的元素,可通过一种通用的获取方式来完成。

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

集合中把这种取元素的方式描述在Iterator接口中。Iterator接口的常用方法如下:

hasNext()方法:用来判断集合中是否有下一个元素可以迭代。如果返回true,说明可以迭代。

next()方法:用来返回迭代的下一个元素,并把指针向后移动一位。

package com.itheima01;

import java.util.ArrayList;

import java.util.Iterator;

 

/*

 * java当中不止ArrayList一个集合,java提供了众多的集合.

 *

 * 不同的容器完成不同方式的数据存储.

 * 不同集合的特点不同,ArrayList有序且可重复且带索引的集合.但是有的集合不带索引.所以如果使用其他集合,可能无法通过get+索引的方式获取元素

 *

 * 所有集合的通用获取元素方法并不是通过索引获取,而是通过迭代器获取.

 * 迭代器:iterator

 */

public class Demo02iterator {

 

    public staticvoid main(String[] args) {

       

        //创建集合对象

        ArrayList<Integer>list = newArrayList<Integer>();

       

        //向集合中添加元素

        list.add(10);

        list.add(100);

        list.add(2000);

       

        //获取该集合的迭代器

        Iterator<Integer>iterator = list.iterator();

       

        //使用迭代器的方法,迭代集合(遍历集合)

        while(iterator.hasNext()) {

            //获取集合中元素

            IntegerthisNumber = iterator.next();

            System.out.println(thisNumber);

        }

    }

 

}

迭代器原理:


package com.itheima01;

 

import java.util.ArrayList;

import java.util.Iterator;

 

/*

 * 集合用来持有数据,所有常用集合都具备了可迭代功能iterator方法,该方法用于迭代集合,该方法才是最为通用的集合迭代方法。

 *

 * 迭代器:集合迭代(集合遍历)的工具

 *

 * 集合的获取迭代器方法

 * public Iterator<E> iterator()  获取某个集合的迭代器实例对象

 *

 * Iterator:迭代器接口

 *      booleanhasNext()  判断集合中是否有下一个元素   不移动元素指针

 *      Enext()  获取集合中下一个元素    移动指针,指向下一个元素

 */

public class Demo03iterator {

 

    public staticvoid main(String[] args) {

       

        //创建集合对象

        ArrayList<Integer>list = newArrayList<Integer>();

       

        //向集合中添加元素

        list.add(10);

        list.add(100);

        list.add(2000);

       

        //调用集合的iterator方法,返回迭代器对象

        Iterator<Integer>itr = list.iterator();

       

        //混合使用hasNextnext方法,循环获取元素

        while(itr.hasNext()) {

            //如果有元素,就获取元素

            IntegerthisNumber = itr.next();

            System.out.println(thisNumber);

        }

       

    }

 

}

泛型:

A:泛型用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数传递。

B:泛型是数据类型的一部分,我们将类名与泛型合并一起看做数据类型

 ArrayList<String> al=newArrayList<String>();//ArrayList<String>看作数据类型

C:泛型的定义:定义泛型可以在类中预支地使用未知的类型。

  //在ArrayList类的add()方法的源码中定义的E e,使用了e

public boolean add(Ee) {

       ensureCapacityInternal(size + 1);  

        elementData[size++] =e;

        return true;

    }

D:泛型的使用:一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。

 ArrayList al=new ArrayList();

 al.add(“abc”);

 al.add(1);//由于在定义集合时没有指定泛型,add()方法的形参为Object类型,所以可以往集合中添加任意任意类型的数据(多态特点)

泛型格式:

class  类名<E,T,……>{//<>中的泛型可以写无数个

  //E,T……能够做为类型在该类内部被使用

}

package com.itheima03.type2;

/*

 * 在该类中定义一个成员变量,使用泛型

 *

 * 不指定其数据类型,是一个不确定的数据类型.

 * 创建不同的对象时,指定不同的数据类型

 *

 */

public classMyClass4Type<T> {

 

    private T myField;

 

    public T getMyField() {

        return myField;

    }

 

    public voidsetMyField(T myField) {

        this.myField= myField;

    }

 

}

 

package com.itheima03.type2;

/*

 * 泛型类:

 *      在类中使用泛型

 *

 * 定义:类名后<变量如:class A<E>{使用E完全类的定义}

 * 使用:创建对象时确定类型

 *

 * 一般定义泛型使用E,T,V,K

 *

 * 泛型方法:

 * 定义:方法返回值前<变量>如:public <T> void method(){使用T}

 * 使用:调用方法时确定类型

 */

public class Demo01type_class {

 

    public staticvoid main(String[] args) {

       

        //测试使用自己定义的泛型类

        MyClass4Type<String>mc4t = newMyClass4Type<String>();

        //调用了使用类泛型的方法

        mc4t.setMyField("Jack");

        StringmyField = mc4t.getMyField();

        System.out.println(myField);

       

        //创建对象时指定泛型为Integer则所有使用了泛型的方法根据对象类型一起改变

        MyClass4Type<Integer>mc4t2 = newMyClass4Type<Integer>();

        mc4t2.setMyField(12);

        System.out.println(mc4t2.getMyField();

    }

}

泛型接口:

interface 接口名<Q,E,R……>{

public abstract voidmethod(T t);//假设定义一个方法

}

class 类名 implements 接口<实际类型>{

      @Override

         public void method(String t) {

            System.out.println(t);

}

}

package com.itheima04.type3;

/*

 * 接口上定义泛型

 */

public interfaceMyInter4Type<T> {

 

    //接口的方法中使用接口泛型

    public abstractvoid method(T t);

}

 


package com.itheima04.type3;

/*

 * 定义类时,就指定接口中的数据类型,定义一个不含泛型的正常类

 */

public class MyClass4Inter implements MyInter4Type<String> {

 

    //使用指定的接口中的数据类型,重写方法

    @Override

    public voidmethod(String t) {

        System.out.println(t);

    }

}


泛型通配符:?

定义:(查看ArrayList的构造方法)无法在类中使用

使用:调用方法时可以给予任意类型。参照Arraylist的构造方法

? extends E代表只要是E类型的子类即可

? super E代表只要是E类型的父类即可











并发修改异常:

在前一个迭代器迭代自定义数据类型的基础上,添加新的需求:

使用集合存储多个Person对象,当遇到16岁的人时,就添加一个90岁的人

  package com.itheima01;

 

/*

 * 人类:

 *      年龄      姓名

 */

public class Person {

 

    private String name;

    private intage;

 

    public Person() {

        super();

    }

 

    public Person(String name, int age) {

        super();

        this.name =name;

        this.age =age;

    }

 

    public String getName() {

        return name;

    }

 

    public voidsetName(String name) {

        this.name =name;

    }

 

    public intgetAge() {

        return age;

    }

 

    public voidsetAge(int age) {

        this.age =age;

    }

 

}

在迭代过程中,使用了集合的方法对元素进行操作。导致迭代器并不知道集合中的变化,容易引发数据的不确定性。

解决并发修改异常,重新获取迭代器

package com.itheima01;

import java.util.ArrayList;

import java.util.Iterator;

 

/*

 使用集合存储多个Person对象,当遇到16岁的人时,就添加一个90岁的人

 

 该例中可能会产生并发修改异常:迭代器所认为的集合状态与集合真正的状态不统一了!就会出现该异常.

 */

public classDemo05ConcurrentModificationException {

 

    public staticvoid main(String[] args) {

        //创建集合对象

        ArrayList<Person>list = new ArrayList<Person>();

        //向集合中添加元素

        Personp = new Person("Jack",18);

        Personp2 = new Person("Rose",16);

        Personp3 = new Person("Trump",62);

        Personp4 = new Person("Obama",56);

        Personp5 = new Person("Castro",90);

       

        list.add(p);

        list.add(p2);

        list.add(p3);

        list.add(p4);

        //调用集合的iterator方法,返回迭代器对象

        Iterator<Person>itr = list.iterator();

       

        //混合使用hasNextnext方法,循环获取元素

        while(itr.hasNext()) {

            //如果有元素,就获取元素

            PersonthisP = itr.next();

            //判断年龄是否为16

            if(thisP.getAge() == 16) {

                //如果存在16岁的人,就加入90岁的卡斯特罗

                list.add(p5);

                //当集合加入了一个元素后,就不要再使用迭代器操作元素了

                break;

            }

        }

       

        //重新打印集合结果

        Iterator<Person>itr2 = list.iterator();

       

        while (itr2.hasNext()) {

            Personperson = (Person) itr2.next();

            System.out.println(person.getAge()+"岁的"+person.getName());

        }

    }

增强for循环遍历集合

package com.itheima01;

 

import java.util.ArrayList;

 

/*

 * foreach循环(又叫增强for循环)来完成容器中元素的获取

 *

 * 增强for循环用来迭代集合或数组,格式如下:

 * for(容器内类型临时变量:容器){

 *      内部可以直接使用临时变量访问数据

 * }

 *

 * 增强for循环源代码底层就是迭代器.所以不能在增强for循环的过程当中为集合添加或者删除元素.因为会产生并发修改异常.

 * 所以,增强for循环只用来查看数据,不作数据修改.

 */

public class Demo06foreach {

 

    public staticvoid main(String[] args) {

 

        //创建集合对象

        ArrayList<Integer>list = newArrayList<Integer>();

        //向集合中添加元素

        list.add(10);

        list.add(100);

        list.add(2000);

       

        //使用增强for循环迭代集合

        for(Integer thisNumber : list) {

            System.out.println(thisNumber);

        }

        System.out.println("=======================");

        //增强for循环便利数组

        String[]arr = {"Jack","Rose","Trump","Obama"};

       

        for (String thisName : arr) {

            System.out.println(thisName);

        }

    }

}

LinkedList:与ArrayList不同,LinkedList是方便添加删除的List。实际开发中对一个元素的添加与删除经常涉及到首尾操作。

LinkedList采用链表存储方式,优点在于插入、删除元素时效率比较高。

每种集合的特点不同(如更适合增删还是更适合查找),是因为底层的数据结构不同。

数据结构指的数据存储和组织方式, 这里介绍最常用的数据结构:

栈结构:容器先进后出规则

 * stack栈结构:先进后出

 *

 * LinkedList是支持栈结构的.

 * 对应的方法

 *      push压栈

 *      pop弹栈

 *      peek查询出即将要弹出的是哪个元素,检查有没有要弹出的元素

 *

 * java提供了一个专门用于栈结构的类,Stack

 */

publicclass Demo02stack {

 

    publicstaticvoid main(String[] args) {

 

        //创建栈结构的集合

        LinkedList<String> stack = newLinkedList<String>();

       

        stack.push("Jack");

        stack.push("Rose");

        stack.push("Trump");

       

        System.out.println(stack);

       

        //获取一个元素,此时,由于是栈结构,所以获取的是最后压栈的元素

        String popName = stack.pop();

        System.out.println(popName);

        //弹栈动作,集合中减少元素

        System.out.println(stack);

       

        String peekName = stack.peek();

        System.out.println(peekName);

        //peek查看元素不会减少元素

        System.out.println(stack);

    }

 

}

 

数组结构:一块连续的存储区域

链表结构:每个元素指向下一个元素


队列结构:

容器先进先出的规则

* queue队列结构:

 *

 * LinkedList是支持队列结构的

 * 对应的方法

 *      offer加入队列

 *      poll离开队列

 *      peek查询出即将要离开队列的是哪个元素,检查有没有要离开队列的元素

 */

publicclass Demo03queue {

 

    publicstaticvoid main(String[] args) {

       

        //创建栈结构的集合

        LinkedList<String> queue = newLinkedList<String>();

       

        queue.offer("Jack");

        queue.offer("Rose");

        queue.offer("Trump");

        System.out.println(queue);

       

        String pollName = queue.poll();

        System.out.println(pollName);

        System.out.println(queue);

       

        String peekName = queue.peek();

        System.out.println(peekName);

        System.out.println(queue);

    }

}

ArrayList数组实现的原理

数组实现的特点: 查询快,增删慢

原因:

         查询快: 由于数组的索引支持,那么可以通过索引直接计算出元素的地址值,因此就可以直接通过

                       元素的地址值获取到指定的元素

增删慢: 由于在添加元素的时候,实际上底层会先创建一个新数组(新数组的长度为原数组的长度+1),

           那么在添加新元素的时候,先需要对数组中原有的数据进行拷贝,其次在末尾进行添加新的元素

       因此,这样操作的效率的极低的(删除元素 刚好和添加的操作相反)

 

 LinkedList链表实现的原理

链表结构: 查询慢,增删快

查询慢:由于不能直接找到元素的地址,需要上一个元素推导出下一个元素的地址,

这种查询速度较慢

增删快:在添加的时候,只需要更改元素所记录的地址值即可


 HashSet的特性和基本使用

HashSet是Set接口的子类,不包含重复元素相同元素,且无序。

HashSet下还有子类LinkedHashSet,可预测迭代顺序的Set集合。

/*

 * HashSet,不包含重复元素相同元素,且无序.不提供索引,所以不能通过索引获取元素,只能通过迭代器访问数据.

 */

publicclass Demo01HashSet {

 

    publicstaticvoid main(String[] args) {

 

        //创建集合对象

        HashSet<String> set = newHashSet<String>();

        //向集合中添加元素

        set.add("Jack");

        set.add("Rose");

        set.add("Trump");

        set.add("Obama");

        set.add("Obama");

       

        System.out.println(set);

        //获取元素,只能用迭代器

        Iterator<String> itr = set.iterator();

       

        while(itr.hasNext()) {

            String thisName = itr.next();

            System.out.println(thisName);

        }

       

        System.out.println("================");

        for (String thisName : set) {

            System.out.println(thisName);

        }

    }

}


package com.itheima08.hashset;

 

import java.util.HashSet;

 

/*

 * 求一个字符串"aiodjl;hriWFUADJSVUEHiowfjnivowe"中一共有几个不重复的字母,区分大小写,a,A算两个字符

 *

 * 将字符串拆分成一个个单个字符

 * 判断字符是否为字母

 * 如果是字母,放到一个HashSet集合中

 * 查看集合长度

 */

public class Test {

 

    public static void main(String[] args) {

       

        String s = "aiodjl;hriWFUADJSVUEHiowfjnivowe";

       

        //定义不包含重复元素的HashSet集合

        HashSet<Character> set = new HashSet<Character>();

       

        //将字符串拆分成一个个单个字符

        char[] charArray =s.toCharArray();

       

        //使用增强for循环遍历数组

        for (char c : charArray) {

           

            //判断字符是否为字母

            if(('a'<=c&&c<='z')||('A'<=c&&c<='Z')) {

               

                //如果是字母,放到一个HashSet集合中

                set.add(c);

            }

        }

       

        //查看集合长度

        System.out.println("在该字符串中,一共存在不重复的字母"+set.size()+"");

    }

}

ArrayList中Contains方法如何判断是否有重复元素

自定义类型Person类是Object类的子类,所以Person具备equals方法contains方法会调用参数的equals方法,

依次与集合当中已经存在的Person对象比较.当Person类没有重写equals方法时,直接使用Object类基础过来的equals方法,

而该方法比较的是对象地址值当Person类重写equals方法后,就可以讲比较规则由比较地址值改为比较属性值

public classDemo02ArrayList_contains {

 

    public staticvoid main(String[] args) {

 

//      ArrayList<String> list = new ArrayList<String>();

//     

//      list.add("Jack");

//      list.add("Rose");

//      list.add("Trump");

//     

//      //判断集合中是否存在Jack

//      System.out.println(list.contains("Jack"));

       

        //ArrayList当中存储自定义数据类型Person

        ArrayList<Person>list2 = newArrayList<Person>();

       

        Personp = new Person("Jack",18);

        Personp2 = new Person("Rose",16);

        Personp3 = new Person("Trump",62);

       

        list2.add(p);

        list2.add(p2);

        list2.add(p3);

       

        System.out.println(list2.contains(new Person("Jack",18)));

//      System.out.println(list2.contains(p));

    }

自定义类需要满足咱们认为的效果,也就是不同的对象但是属性值相同就认为是同一个对象

在集合里只存其一的效果,就必须重写equals方法,且更改该方法里的比较规则

/*

     * 如果没有重写该equals方法,则比较地址值.

     * 我们希望比较两个对象时,比较属性内容,所以重写该方法.

     */

    @Override

    publicboolean equals(Object obj) {

        System.out.println("equals方法被调用了");

       

        //this:contains方法的参数对象         obj:集合当中老元素

        //将Object类型的obj强转为子类类型

        Person otherP = (Person)obj;

       

        //比较姓名

        if(!this.name.equals(otherP.name)) {

            returnfalse;

        }

        //比较年龄

        if(this.age != otherP.age){

            returnfalse;

        }

        //如果所有属性值均相同,就返回true

        returntrue;

    }

HashSet判断元素唯一性规则

Set集合不能存放重复元素,其添加方法在添加时会判断是否有重复元素,有重复不添加,没重复则添加。

HashSet集合由于是无序的,其判断唯一的依据是元素类型的hashCode与equals方法的返回结果。规则如下:

先判断新元素与集合内已经有的旧元素的HashCode值

如果不同,判断元素不同。

       如果相同,再判断equals比较结果,返回true则相同,返回false则仍然不同。

所以,使用HashSet存储自定义类型,如果没有重写该类的hashCode与equals方法,则判断重复时,使用的地址值,如果想通过内容比较元素是否相同,需要重写该类的hashcode与equals方法。

hashCode方法重写规则:将该对象的各个属性值hashCode相加即是整个对象的HashCode值。如果是基本类型,类似int,则直接返回int值就是该属性的hash值,如果是引用类型,类似String,就调用该成员变量的hashCode方法返回该成员变量hash值。这样可以根据对象的内容返回hashCode值,从而可以根据hashCode判断元素是否唯一。

但是由于在一些”碰巧的”情况下,可能出现内容不同但hashCode相同的情况,为了避免这些情况,我们加入一些干扰系数。

可是加入干扰系数后,仍会出现一些”碰巧”的情况,所以我们还要进行equals的二次判断

//没有重写equals方法,equals方法继承父类方法,通过判断地址值比较对象

    @Override

    publicboolean equals(Object obj) {

        System.out.println("equals方法被调用了");

       

        //this:add方法的参数对象         obj:集合当中老元素

        //将Object类型的obj强转为子类类型

        Animal otherA = (Animal)obj;

       

        //比较姓名

        if(!this.name.equals(otherA.name)) {

            returnfalse;

        }

        //比较年龄

        if(this.age != otherA.age){

            returnfalse;

        }

        //如果所有属性值均相同,就返回true

        returntrue;

    }

 

    //没有重写hashCode方法时,hashCode方法继承父类方法,返回的是地址值

    //重写hashCode方法,通过属性值返回一个整数数字

    //即对象的hashCode值,就是各个属性的hashCode值之和

    //引用数据类型属性,调用hashCode方法回去

    //基本数值类型属性,直接就是数值本身

    @Override

    publicint hashCode() {

       

        //张三   18   >>  56*系数  + 18  = 74

        //李四   56   >>  18*系数  + 56  = 74

        //理想上,不同属性值应该返回不同的hashCode值,可以在每次结果后乘以一个固定系数,避免该情况发生

       

        //定义变量,记录要返回的hashCode值

        int thisHashCode = 0;

       

        //获取name属性的hashCode值

        thisHashCode += name.hashCode()*17;

        //获取age数只给你的hashCode值

        thisHashCode += age;

       

        return thisHashCode;

    }

 

//eclipse可以使用快捷键自动生成对应的hashCode方法与equals方法

    @Override

    publicint hashCode() {

        //定义系数

        finalint prime = 31;

        //定义返回的hashCode值

        int result = 1;

        //每次将结果*系数,再加下一个成员变量,可以大大降低不同成员变量返回相同hashCode值的情况

        result = prime * result + age;

        result = prime * result + ((name == null) ? 0 : name.hashCode());

        return result;

    }

 

    @Override

    publicboolean equals(Object obj) {

        //自身与自身比较直接返回true

        if (this == obj)

            returntrue;

        //参数是null直接返回false

        if (obj == null)

            returnfalse;

        //如果调用方法的类型与参数类型不一样,则直接返回false

        if (getClass() != obj.getClass())

            returnfalse;

        //如果类型相同,就转成(强制类型转换)相同的类型继续比较属性值

        Animal other = (Animal) obj;

        //比较年龄

        if (age != other.age)

            returnfalse;

        //比较姓名

        if (name == null) {

            if (other.name != null)

                returnfalse;

        } elseif (!name.equals(other.name))

            returnfalse;

        //如果一切不相同的情况都不符合,则说明两个对象的属性值相同,返回true

        returntrue;

    }


双列集合Map:

双列集合是每个元素都有键与值两部分组成的集合,记录的是键值对对应关系。即通过键可以找到值。

常用子类:

最常用的双列集合是Map下的子类HashMap。

Hashtable也是Map集合的一种已被HashMap取代。

 

Map集合的特点,如是否可重复,是否有序仅作用在键上,如HashMap集合的键不得重复,值可以重复。

1.1.1    案例代码一:

packagecom.itheima09.map;

 

importjava.util.Collection;

importjava.util.HashMap;

importjava.util.Iterator;

importjava.util.Set;

 

/*

 * Map:双列集合,每个元素分为键与值两部分,是一个键值得对应关系.我们经常使用键找值

 *

 * 最常用的Map集合是HashMap:键是唯一的且无序

 *

 * 用法:

 *      

 */

publicclass Demo01Test_Map {

        publicstatic void main(String[] args) {

            //创建集合对象

            HashMap<String,String> map = new HashMap<String,String>();

            //向集合中添加元素

            map.put("姓名", "Jack");

            map.put("性别", "");

            map.put("年龄", "18");

            map.put("分数", "18");

 

            //可以通过键获取值

            String value =map.get("姓名");

            System.out.println(value);

        }

}

1.1      Map基本使用

A:Map(HashMap)的使用:创建对象时加入两个泛型。

Map<k,v>

key - 此映射所维护的键的类型

value - 映射值的类型

 

B:常用方法:

public V put(K key,V value)    //加入元素,则新值会覆盖掉旧值

public V get(Object key)           //根据键找值

 

1.1.1    案例代码二:

packagecom.itheima09.map;

 

importjava.util.Collection;

importjava.util.HashMap;

importjava.util.Iterator;

importjava.util.Set;

 

/*

 * Map:双列集合,每个元素分为键与值两部分,是一个键值得对应关系.我们经常使用键找值

 *

 * 最常用的Map集合是HashMap:键是唯一的且无序

 *

 * 用法:

 *       创建对象时,要分别制定键的泛型与值的泛型

 *

 *       Map(HashMap)的使用:创建对象时加入两个泛型。

 *       Map<k,v>

 *       key- 此映射所维护的键的类型

 *       value- 映射值的类型

 *

 *       常用方法:

 *           publicV put(K key,V value)//加入元素,则新值会覆盖掉旧值

 *           publicV get(Object key)    //根据键找值

 *           publicSet<K> keySet()      //返回所有键的集合

 *           publicCollection<V> values()  //返回所有值的集合

 *

 */

publicclass Demo01Test_Map {

 

public static voidmain(String[] args) {

   

    //创建集合对象

    HashMap<String, String> map = newHashMap<String, String>();

   

    //向集合中添加元素

    map.put("及时雨", "宋江");

    map.put("玉麒麟", "卢俊义");

    map.put("智多星", "高俅");

    map.put("智多星", "吴用");

   

    System.out.println(map);

    //可以通过键获取值

    String name = map.get("及时雨");

    System.out.println(name);

   

    String name2 = map.get("母夜叉");

    System.out.println(name2);

   

}

}

1.1      Map集合遍历方式1

第1种遍历方式是,使用Map集合的keySet()方法

 

A:思路:

* 通过keySet()方法获取所有键的集合

* 遍历键的集合,获取到每一个键

* 根据键找值

1.1.1    案例代码三:

packagecom.itheima09.map;

 

importjava.util.Collection;

importjava.util.HashMap;

importjava.util.Iterator;

importjava.util.Set;

/*

 * Map:双列集合,每个元素分为键与值两部分,是一个键值得对应关系.我们经常使用键找值

 *

 * 最常用的Map集合是HashMap:键是唯一的且无序

 *

 * 用法:

 *       创建对象时,要分别制定键的泛型与值的泛型

 *

 *       Map(HashMap)的使用:创建对象时加入两个泛型。

 *       Map<k,v>

 *       key- 此映射所维护的键的类型

 *       value- 映射值的类型

 *

 *       常用方法:

 *           publicV put(K key,V value)//加入元素,则新值会覆盖掉旧值

 *           publicV get(Object key)    //根据键找值

 *           publicSet<K> keySet()      //返回所有键的集合

 *           publicCollection<V> values()  //返回所有值的集合

 *       Map没有迭代器方法,最常用的遍历方法:先获取所有键的集合,迭代该集合,依次获取每一个键.通过键找值.

 */

publicclass Demo01Test_Map {

 

public static voidmain(String[] args) {

   

    //创建集合对象

    HashMap<String, String> map = newHashMap<String, String>();

   

    //向集合中添加元素

    map.put("及时雨", "宋江");

    map.put("玉麒麟", "卢俊义");

    map.put("智多星", "高俅");

    map.put("智多星", "吴用");

   

//返回所有键的集合

    Set<String> keySet = map.keySet();

    System.out.println(keySet);

   

    //返回所有值得集合

    Collection<String> values = map.values();

    System.out.println(values);

   

    //map集合的常用遍历

    Set<String> keySet2 = map.keySet();

    System.out.println("==========================");

    //迭代所有键的Set集合,依次获取每一个键

    Iterator<String> iterator = keySet2.iterator();

   

    while(iterator.hasNext()) {

        String thisKey = iterator.next();

        //通过键找值,记住这里使用map集合通过键找值

        String thisValue = map.get(thisKey);

        System.out.println(thisKey+"="+thisValue);

    }

   

}

}

1.1      Map集合遍历方式2

第2种遍历方式是,使用Map集合的entrySet()方法

 

A:思路:

* 通过entrySet()方法获取所有键值对对象的集合

* 遍历键值对对象的集合,获取到每一个键值对对象

* 根据键值对对象找键和值

   

B: entrySet()方法解释

Set<Map.Entry<K,V>> entrySet()    方法用于返回某个集合所有的键值对对象。

    Map.Entry说明Entry是Map的内部接口,将键和值封装成了Entry对象,并存储在Set集合中。可以从一个Entry对象中获取一个键值对的键与值。

 

C:  Entry中的方法如下:

       K getKey()      获取键

       V getValue()    获取值

1.1.1    案例代码四:

packagecom.itheima09.map;

 

importjava.util.HashMap;

importjava.util.Map.Entry;

importjava.util.Set;

 

/*

 * Map集合的第二种遍历方式:

 *

 *   Set<Map.Entry<K,V>>  entrySet()   方法用于返回某个集合所有的键值对对象。

 *   Entry将键值对对应关系封装成了对象。可以从一个Entry对象中中获取一个键值对的键与值。

 *

 *   Map.Entry是一个嵌套类

 *

 * Entry中的方法如下:

 * K getKey()       获取键

 * V getValue()     获取值

 */

publicclass Demo02Entry {

 

    public staticvoid main(String[] args) {

        //创建集合对象

        HashMap<String,String> map = new HashMap<String,String>();

   

        //向集合中添加元素

        map.put("及时雨", "宋江");

        map.put("玉麒麟", "卢俊义");

        map.put("智多星", "吴用");

   

        //获取集合中所有的键值对对象的Set集合

        Set<Entry<String,String>>entrySet = map.entrySet();

   

        //迭代集合,依次获取每一个键值对对象

        for(Entry<String,String>thisEntry: entrySet) {

            //通过键值对对象获取键

            String key = thisEntry.getKey();

            //通过键值对对象获取值

            String value =thisEntry.getValue();

            System.out.println(key+":"+value);

        }

    }

        }

1.1      LinkedHashMap

A:LinkedHashMap:

               *Linked链表结构,保证元素有顺序

               *Hash结构保证元素唯一

               *以上约束对键起作用

 

B: LinkedHashMap的特点

               * 底层是链表实现的可以保证怎么存就怎么取

 

1.1.1    案例代码五:

package com.itheima09.map;

 

import java.util.LinkedHashMap;

import java.util.Set;

 

/*

 * LinkedHashMap:

 *           Linked链表结构,保证元素有顺序

 *           Hash结构保证元素唯一

 *           以上约束对键起作用

 */

publicclass Demo03LinkedHashMap {

 

publicstaticvoid main(String[] args) {

   

    //创建集合对象

    LinkedHashMap<String,String> map = new LinkedHashMap<String, String>();

    //向集合中添加元素

    map.put("近平", "丽媛");

    map.put("路人甲", "路人乙");

    map.put("Jack", "Rose");

    map.put("Jack", "Lily");

   

    //观察集合元素

    System.out.println(map);

   

    //遍历集合

    //获取所有键的集合

    Set<String> keys = map.keySet();

   

    //迭代所有键的集合

    for(String thisKey: keys) {

        //通过键找值

        String thisValue = map.get(thisKey);

        //打印信息

        System.out.println(thisKey+":"+thisValue);

    }

}

}

1.1      可变参数

Collections中有一个方法可以一次加入多个元素

  publicstatic <T> boolean addAll(Collection<? super T> c,T... elements)

  该方法使用到了可变参数,即定义时并不知道要传入多少个实际参数。此时定义成...的方式,此时可以在调用该方法时,一次传入多个参数。传入的多个数将被自动组织成数组,我们只要操作生成的数组即可。

  注:可变参数只能放在最后定义。可变参数方法本质是数组,所以不可以与数组类型参数重载。

1.1.1    案例代码六:

package com.itheima10CollectionOthers;

 

import java.util.ArrayList;

import java.util.Collection;

import java.util.Collections;

 

/*

 * 可变参数:

 *      参数可变

 * Collections:

 * public static <T> booleanaddAll(Collection c<? super T>, T... elements)  将指定的元素添加到集合

 *

 * 数据类型...     代表可变参数即可以传入任何多个该类型的数据

 * 可变参数不能放在前边,只能放在最后

 * 可变参数的方法与数组的方法不能重载,因为可变参数实质上就是数组

 */

public class Demo01args {

 

    public staticvoid main(String[] args) {

       

        Collection<String>c = newArrayList<String>();

        //c集合中添加N个元素

        Collections.addAll(c, "Jack","Rose","Trump");

        System.out.println(c);

        System.out.println("=====================================");

        int sum = add(10,20,30,40);

        System.out.println(sum);

    }

   

    //...定义可变参数,a表示了所有传进来的参数,a就是一个数组名称,存储了所有的参数

    //求任意个数的和

    public staticint add(int...a) {

       

        //用来记录所有数的和

        int sum =0;

        //遍历可变参数a代表的数组

        for(inti=0; i<a.length; i++) {

            int j = a[i];

            System.out.println(j);

            //每次遇到一个数,就将该数累加到和中

            sum += j;

        }

       

        //返回和

        return sum;

    }

   

    /*可变参数方法不能与数组方法重载

    public static void add(int[] x) {

       

    }

    */

 

}

1.1      Collections的shuffle方法

shuffle方法的作用:

打乱集合中元素顺序

1.1.1    案例代码七:

package com.itheima10CollectionOthers;

 

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

 

/*

 * Collections:集合工具类,包含了众多集合的方法

 *

 * public static <T> voidsort(List<T> list)                //排序

 * public static <T> intbinarySearch(List<?> list,T key)   //查找元素索引

 * 二分法查找:在一个集合当中,查找一个指定元素的索引是多少,如果不存在该元素,就返回负数索引

 * 二分法查询必须要求集合中的元素排好顺序

 *

 * public static void shuffle(List<?>list)             //打乱元素顺序

 *

 * 有顺序(有序):第一个元素是多少,第二个元素是多少,第几个元素对应的是第几,顺序不变.

 * 排序:不管是第几个放的,只要到集合中(Integer集合为例),就按照一定的顺序重新排列了.

 */

public class Demo02Collections {

 

    public staticvoid main(String[] args) {

        //准备集合及元素

        List<Integer>list = newArrayList<Integer>();

       

        list.add(2);

        list.add(7);

        list.add(6);

        list.add(10);

        list.add(9);

       

        System.out.println(list.get(0));

       

        //打乱集合顺序

        Collections.shuffle(list);

        //打印集合

        System.out.println(list);

    }

 

}

 

1.2      Collections的sort方法

A:sort方法的作用:

对集合中元素排序

 

  B:sort方法签名

   public static<T> void sort(List<T> list)

 

有顺序(有序):第一个元素是多少,第二个元素是多少,第几个元素对应的是第几,顺序不变.

排序:不管是第几个放的,只要到集合中(以Integer集合为例),就按照一定的顺序重新排列了.

1.2.1     案例代码八:

package com.itheima10CollectionOthers;

 

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

 

/*

 * Collections:集合工具类,包含了众多集合的方法

 *

 * public static <T> voidsort(List<T> list)                //排序

 * public static <T> intbinarySearch(List<?> list,T key)   //查找元素索引

 * 二分法查找:在一个集合当中,查找一个指定元素的索引是多少,如果不存在该元素,就返回负数索引

 * 二分法查询必须要求集合中的元素排好顺序

 *

 * public static void shuffle(List<?>list)             //打乱元素顺序

 *

 * 有顺序(有序):第一个元素是多少,第二个元素是多少,第几个元素对应的是第几,顺序不变.

 * 排序:不管是第几个放的,只要到集合中(Integer集合为例),就按照一定的顺序重新排列了.

 */

public class Demo02Collections {

 

    public staticvoid main(String[] args) {

        //准备集合及元素

        List<Integer>list = newArrayList<Integer>();

       

        list.add(2);

        list.add(7);

        list.add(6);

        list.add(10);

        list.add(9);

       

       

        //将集合排好顺序(Integer数字的自然顺序是从小到大排列)

        Collections.sort(list);

        System.out.println(list);

       

        //如果放字符串(字符串的顺序是字母排序.)

        List<String>list2 = newArrayList<String>();

       

        list2.add("a");

        list2.add("d");

        list2.add("c");

        list2.add("b");

       

        System.out.println(list2);

        Collections.sort(list2);

        System.out.println(list2);

       

        //如果放Person对象(人这个自定义数据类型的对象没有比较顺序,不知道什么样的人叫大,什么样的人叫小,所以人不能比较.就不能排序)

        Personp = newPerson("Jack",18);

        Personp2 = newPerson("Rose",20);

        Personp3 = newPerson("Adda",24);

       

        List<Person>list3 = newArrayList<Person>();

        list3.add(p);

        list3.add(p2);

        list3.add(p3);

       

//      Collections.sort(list3);

    }

}

1.1      Collections的二分法查找

A: binarySearch方法的作用:

查找集合中指定元素的索引

 

  B:binarySearch方法签名

public static <T> int binarySearch(List<?> list,T key)

 

1.1.1    案例代码九:

package com.itheima10CollectionOthers;

 

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

 

/*

 * Collections:集合工具类,包含了众多集合的方法

 *

 * public static <T> voidsort(List<T> list)                //排序

 * public static <T> intbinarySearch(List<?> list,T key)   //查找元素索引

 * 二分法查找:在一个集合当中,查找一个指定元素的索引是多少,如果不存在该元素,就返回负数索引

 * 二分法查询必须要求集合中的元素排好顺序

 *

 * public static void shuffle(List<?>list)             //打乱元素顺序

 *

 * 有顺序(有序):第一个元素是多少,第二个元素是多少,第几个元素对应的是第几,顺序不变.

 * 排序:不管是第几个放的,只要到集合中(Integer集合为例),就按照一定的顺序重新排列了.

 */

public class Demo02Collections {

 

    public staticvoid main(String[] args) {

        //验证二分法查找元素必须有序

        List<Integer>list4 = newArrayList<Integer>();

       

        list4.add(2);

        list4.add(7);

        list4.add(6);

        list4.add(10);

        list4.add(9);

       

        int binarySearch= Collections.binarySearch(list4, 9);

        System.out.println(binarySearch);

       

        Collections.sort(list4);

        System.out.println(list4);

        int binarySearch2= Collections.binarySearch(list4, 9);

        System.out.println(binarySearch2);

    }

 

}

 

1.2      Arrays的toString方法

A: toString方法的作用:

返回字符串内容

 

B:toString方法签名:

publicstatic String toString(Xxx[] a)

1.2.1    案例代码十:

package com.itheima10CollectionOthers;

 

import java.util.Arrays;

 

/*

 * Arrays:数组工具类,包含了许多数组工具方法

 *

 * public static int binarySearch(Xxx[]a,Xxx key)      //查找元素索引

 * public static void sort(Xxx[] a)                 //排序

 * public static String toString(Xxx[]a)           //返回字符串内容

 */

public class Demo03Arrays {

 

    public staticvoid main(String[] args) {

       

        String[]arr = {"Jack","Rose","Trump"};

//      Integer[] arr = {3,1,5,6,2,19};

        System.out.println(arr);

       

        //调用ArraystoString方法

        System.out.println(Arrays.toString(arr));

        System.out.println(Demo03Arrays.toString(arr));

       

    }

}

 

1.3      数组转集合

数组转集合使用的是,Arrays类中的asList方法

  方法签名如下:

         public static <T> List<T>asList(T... a)

 

  解释:

         静态方法,直接类名.方式调用

         方法的形参是可变参数类型,可变参数本质也是数组,传入实际数组,将该数组转成集合返回

        

 

  注意:

         数组转成集合之后,该集合不支持添加或者删除操作,否则会抛出UnsupportedOperationException异常

1.3.1    案例代码十一:

package com.itheima10CollectionOthers;

 

import java.util.Arrays;

import java.util.List;

 

/*

 * 数组转集合

 *

 * Arrays:

 * publicstatic <T> List<T> asList(T... a)                //数组转集合

 *

 * UnsupportedOperationException:不支持的添加或者删除操作

 */

public class Demo04Arrays_asList{

 

    public staticvoid main(String[] args) {

       

        List<String>newList = Arrays.asList("Jack","Rose","Trump");

        System.out.println(newList);

       

        //使用asList转成的集合,不能添加或者删除元素,该方法返回的集合长度不能改变!所以,22行运行报错.

        newList.add("Obama");

        System.out.println(newList);

    }

}

 

 

1.4      集合转数组

集合ArrayList转数组使用的是,ArrayList中的toArray()方法。

该方法是重载的方法:

   public Object[] toArray()

         public <T> T[] toArray(T[] a)

 

1.4.1    案例代码十二:

package com.itheima10CollectionOthers;

 

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

 

/*

 * 集合转数组:

 *      集合ArrayList转为数组的方法为ArrayList的以下两个方法:

 *      publicObject[] toArray()                           //集合转数组

 *      public<T> T[] toArray(T[] a)

 */

public classDemo05ArrayList_toArray {

 

    public staticvoid main(String[] args) {

       

        List<Integer>list = newArrayList<Integer>();

       

        list.add(2);

        list.add(7);

        list.add(6);

        list.add(10);

        list.add(9);

       

        //调用方法,将集合转为Object类型数组

        Object[]objArr = list.toArray();

        System.out.println(Arrays.toString(objArr));

       

        Integeri = (Integer) objArr[0];

        //如果使用元素类型Integer的特有方法,则必须先强转成Integer,否则intValue方法不能使用,比较麻烦

        System.out.println(i.intValue());

        System.out.println("=======================");

        //调用方法,将集合转为带类型的数组

        Integer[]intArr = newInteger[2];

        Integer[]returnArr = list.toArray(intArr);

       

        //如果参数数组足够放下集合中所有元素,就放入参数数组中,返回参数数组

        //如果参数数组无法放下集合中所有元素,则参数数组只起到确定类型作用,方法逻辑会自动创建新数组存储集合内容,并返回.

        System.out.println(Arrays.toString(intArr));

        System.out.println(Arrays.toString(returnArr));

        //带泛型后,元素类型直接就是集合中的元素类型,避免了强转的问题

        Integerinteger = returnArr[0];

        System.out.println(integer.intValue());

    }

 

}

斗地主发牌洗牌案例:

需求分析:

A:准备牌:

完成数字与纸牌的映射关系:

使用双列Map(HashMap)集合,完成一个数字与字符串纸牌的对应关系(相当于一个字典)。

B:洗牌:

通过数字完成洗牌发牌

C:发牌:

将每个人以及底牌设计为ArrayList<String>,将最后3张牌直接存放于底牌,剩余牌通过对3取模依次发牌。

存放的过程中要求数字大小与斗地主规则的大小对应。

将代表不同纸牌的数字分配给不同的玩家与底牌。

D:看牌:

通过Map集合找到对应字符展示。

通过查询纸牌与数字的对应关系,由数字转成纸牌字符串再进行展示。

package com.itheima09.map;

 

import java.util.ArrayList;

import java.util.Collections;

import java.util.HashMap;

import java.util.Map;

 

/*

 * 按照斗地主的规则,完成洗牌发牌的动作。

 * ♣♦♠♥

 * 具体规则:

 *    使用54张牌打乱顺序

 *    三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。

 *

 * 逻辑分析:

 *

 * 每张牌由花色数字两部分组成,我们可以使用花色集合与数字集合嵌套迭代完成每张牌的组装。

 * 使用一个Map集合,<<将小的数字与小的牌对应起来>>,做成Map集合的键与值

 * :

 *    :数字

 *    :花色+数字的字符串()

 *

 * 准备牌:

 * 牌可以设计为一个ArrayList<Integer>,每个数字为一张牌。

 * 牌由Collections类的shuffle方法进行随机排序。

 * 发牌:

 * 将每个人以及底牌设计为ArrayList<Integer>,将最后3张牌直接存放于底牌,剩余牌通过对3取模依次发牌。

 * 看牌:

 * 将所有集合排序Collections类的sort方法进行排序

 * 将每个集合的数字依次找到对应的纸牌字符串打印出来

 */

public class Test{

 

   public static void main(String[] args) {

     

      //确立纸牌与数字的对应关系

      Map<Integer, String> map = new HashMap<Integer, String>();

     

      //花色集合

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

      colors.add("♣");

      colors.add("♦");

      colors.add("♠");

      colors.add("♥");

     

      //数字集合,加入数字时,直接按照从小到大的顺序加入

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

      for (int i = 3; i <= 10; i++) {

         numbers.add(i+"");

      }

      Collections.addAll(numbers, "J","Q","K","A","2");

     

      //定义数字,用于记录数字与字符串纸牌的对应关系

      int card_number = 0;

     

      //遍历数字集合,使用每个数字匹配每种花色

      for (String thisNumber : numbers){

         //使用数字匹配所有花色

         for (String thisColor : colors) {

            String thisCard = thisColor+ thisNumber;

            //匹配数字与字符串纸牌,完成对应关系

            map.put(card_number, thisCard);

            //每加入一个对应关系,就让数字加1

            card_number++;

         }

      }

     

      //加入大小王对应关系

      map.put(card_number++, "");

      map.put(card_number, "");

      System.out.println(map);

     

      //准备牌:

      ArrayList<Integer> poker = new ArrayList<Integer>();

      for (int i = 0; i < 54; i++) {

         poker.add(i);

      }

      //打乱顺序

      Collections.shuffle(poker);

     

      //发牌:

      ArrayList<Integer> player01 = new ArrayList<Integer>();

      ArrayList<Integer> player02 = new ArrayList<Integer>();

      ArrayList<Integer> player03 = new ArrayList<Integer>();

      ArrayList<Integer> dipai = new ArrayList<Integer>();

     

     

      for (int index = 0; index <poker.size(); index++) {

         //通过索引,获取代表牌的数字

         Integer integer_card =poker.get(index);

        

         //是否为底牌的判断

         if(index>=51) {

            dipai.add(integer_card);

         }else {

            //3取模判断发给哪个玩家

            if(index%3==0) {

                player01.add(integer_card);

            }else if(index%3==1){

                player02.add(integer_card);

            }else {

                player03.add(integer_card);

            }

         }

      }

     

      //将所有集合排序Collections类的sort方法进行排序

      Collections.sort(player01);

      Collections.sort(player02);

      Collections.sort(player03);

      Collections.sort(dipai);

     

      //看牌

      for (Integer integer : player01){

         String realCard =map.get(integer);

         System.out.print(realCard+");

      }

      System.out.println();

      for (Integer integer : player02){

         String realCard =map.get(integer);

         System.out.print(realCard+");

      }

      System.out.println();

      for (Integer integer : player03){

         String realCard =map.get(integer);

         System.out.print(realCard+");

      }

      System.out.println();

      for (Integer integer : dipai) {

         String realCard =map.get(integer);

         System.out.print(realCard+");

      }

   }

}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

brid_fly

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

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

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

打赏作者

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

抵扣说明:

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

余额充值