• 集合到底是什么

    • 数组就是一个集合 集合实际上就是一个容器 可以来容纳其他类型的数据
  • 集合与数组的区别

    • 数组的长度是固定的 集合的长度是可变的
    • 数组中存储的是同一类型的元素,可以存储基本数据类型值。
    • 集合存储的都是对象。而且对象的类型可以不一致。

主要内容

  • Collection集合
  • 迭代器
  • 增强for
  • List集合
  • Set集合

学习目标

  • [ ] 能够使用迭代器对集合进行取元素
  • [ ] 能够使用集合存储自定义类型
  • [ ] 能够说出什么是集合
  • [ ] 能够说出集合与数组的区别
  • [ ] 能够说出ArrayList、LinkedList、Vector区别
  • [ ] 够说出Set集合各种实现类的区别
  • [ ] 能够说出Collection和Map集合的区别
  • [ ] 说出Map集合的常用功能
  • [ ] 能够遍历Map集合
  • [ ] 能够说出各种Map集合实现类的区别
  • [ ] 能够简单阐述HashMap的底层实现
  • [ ] 能够查询和使用集合工具类的相关方法
  • [ ] 能够说出Set与Map的关系

集合框架

Collection接口:单列集合 用来存储一个一个的对象

  • List接口:有序的 可重复 支持索引

    • ArrayList:作为List接口的主要实现类;线程不安全 效率高 底层使用数组存储
    • LinkedList:底层使用双向链表存储 线程不安全 执行效率高
    • Vector:作为List接口的古老实现类线程安全的 效率低 底层使用数组存储
    • Set接口:无序的 不可重复的数据
    • HashSet:作为Set接口的主要实现类 线程不安全的 可以存储NULL值

      • LinkedHashSet:有序 作为HashSet的子类 遍历内部数据时 可以按照添加的顺序遍历 频繁的遍历操作 效率高与HashSet
    • TreeSet:添加数据要求是同一类型
  • Map接口:双列集合 用来存储一对一对的数据(Key - value)

    • HashMap:作为Map的主要实现类;线程不安全 效率高 存储Null的Key和value

      • LinkedHashMap:在HashMap原有的基础上 添加了一对儿指针,指向前一个和后一个元素
    • TreeMap:按照添加的Key-value进行排序 实现排序遍历
    • Hashtable:作为古老的实现类;线程安全 效率低 不能存储Null的Key和value
    • Properties:用来处理配置文件 Key和value都是String类型

Collection 常用功能

属性说明
add添加元素对象到当前集合中
addAll添加新集合中的所有元素对象到当前集合中
remove删除第一个找到的与obj对象equals返回true的元素
removeAll删除所有与coll集合中相同的元素
isEmpty判断当前集合是否为空集合
contains判断当前集合中是否存在一个与obj对象equals返回true的元素
containsAll判断c集合中的元素是否在当前集合中都存在
size查询当前集合中实际存储的元素个数
toArray集合转换为数组
Arrays.asList数组转换为集合
hashCode查询当前对象的哈希值

Collection集合基本使用

package Collection01;

import java.util.*;

public class CollectionTest {
    public static void main(String[] args) {
        //1.添加元素
        Collection coll = new ArrayList();
        coll.add("张三");
        coll.add(new String("Tom"));
        coll.add("李四");

        Collection coll1 =  new ArrayList();
        coll1.add("likedx");
        coll1.add("likedx1");
        coll1.add("李哈哈");
        coll1.add("李四");

        //添加新集合中的所有对象到当前集合中
        coll.addAll(coll1);
        System.out.println(coll);

        //2.删除元素
        //coll.remove("张三");

        //删除所有并且与coll集合中相同的元素
        //coll.removeAll(coll1);
        System.out.println(coll);

        //3.判断元素
        System.out.println("判断coll是否为空的集合" + coll.isEmpty());
        System.out.println("判断张三是否存在Coll集合中" + coll.contains("张三"));
        System.out.println("判断coll1集合中的元素是否在当前集合中都存在" + coll.containsAll(coll1));

        //4.查询
        System.out.println("储存元素的个数为:" + coll.size());

        //集合转换为数组
        Object[] objects = coll.toArray();

        //遍历数组
        for (int i = 0; i < objects.length; i++) {
            System.out.println(objects[i]);
        }

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

        //数组转换为集合Arrays.asList(数组名).var
        List<Object> objects1 = Arrays.asList(objects);
        System.out.println(objects1);

        //查询当前对象的哈希值
        System.out.println(coll.hashCode());


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

        Collection collection = new ArrayList();
        Person p = new Person("张三",20);
        collection.add(p);
        collection.add(new Person("likedx",18));
        collection.add("Tom");

        //判断Tom是否在coll集合当中
        System.out.println(coll.contains(new String("Tom")));

        //判断时会调用obj对象所在类的equals 不重写Person类equals方法为false
        System.out.println(coll.contains(new Person("likedx",18)));

    }
}
class Person{
    private String name;
    private int age;

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

    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 String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }


/*    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }*/

}

Iterator迭代器

Iterator接口

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

基本功能

方法说明
remove删除元素
hasNext判断元素
next输出元素
package Collection01;

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


public class IteratorTest {
    public static void main(String[] args) {
        Collection coll  = new ArrayList();
        coll.add("One");
        coll.add("Two");
        coll.add("Three");
        coll.add("Four");

        System.out.println("当前的数据是:" + coll);

        //创建迭代器对象
        Iterator iterator = coll.iterator();

        System.out.println(iterator.next());
        System.out.println(iterator.next());
        System.out.println(iterator.next());
        System.out.println(iterator.next());
        //输出的次数大于集合中的个数会导致无法获取到下一个元素 出现NoSuchElementException异常
        //System.out.println(iterator.next());

        
        
        //遍历集合 判断有没有元素 有就取出来 继续判断直到结束
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        //删除迭代器中的所有元素
        iterator.remove();

        //再次访问会出错 出现NoSuchElementException异常
        //System.out.println(iterator.next());
    }
}

增强for

增强for循环(也称for each循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。

for(元素的数据类型  变量 : Collection集合or数组){ 
      //遍历的元素
}
  • 遍历集合
public class For_each {
    public static void main(String[] args) {
        Collection coll = new ArrayList();
        coll.add("zhangsan");
        coll.add("lisi");
        coll.add("wangwu");
        coll.add("zhaoliu");

        //遍历集合
        for (Object obj : coll) {
            System.out.println(obj);
        }
      }
     }
  • 遍历数组
public class For_each {
    public static void main(String[] args) {


        //遍历数组
        int [] arr = new int[]{1,2,3,4,5,6,7,8};
        for (int i : arr) {
            System.out.println(i);
        }

        String [] str = new String[]{"zhangsan","lisi","wangwu","zhaoliu"};
        for (String i : str) {
            System.out.println(i);
        }
    }
}
  • 练习题
public class For_each {
    public static void main(String[] args) {
        String [] arr = new String[]{"MM","MM","MM"};

/*        for (int i = 0; i < arr.length; i++) {
            arr[i] = "GG";
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]); //输出GG
        }*/
 
        for (String str : arr) {
            str = "GG"; //此str非str str为局部变量
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);//输出MM
        }
    }
}

List集合

特点:

  1. 作为List接口的主要实现类;线程不安全 效率高 底层使用数组存储
  2. 元素有序 可重复

List接口中常用方法

方法说明
add(Object obj)
remove(int index) / remove(Object ele)
set(int index,Object ele)
get(int index)
add(int index,Object ele)
size()长度
Iterator迭代方式 增强for循环 普通的循环遍历
indexof(Object o)字符串返回索引
lastIndexOf(Object o)重复字符串返回索引
contains(Object o)包含某字符串
isEmpty是否为空
addAll(Collection c)插入新集合
removeAll(Collection c)删除新集合
clear清空
clone克隆
toArray集合转数组
Arrays.asList(集合的变量)数组转集合
public class ArrayList_Test {
    public static void main(String[] args) {
        ArrayList arr = new ArrayList();

        //增加数据
        arr.add("zhangsan");
        arr.add("lisi");
        arr.add("wangwu");

        //删除数据
        Object remove = arr.remove(1);
        System.out.println(remove); //查看删除的数据

        boolean lisi = arr.remove("zhangsan");
        System.out.println(lisi); //返回布尔类型 判断是否删除成功

        arr.add("zhaoliu");
        arr.add("aa");
        arr.add("bb");

        //修改数据
        Object likedx = arr.set(0, "likedx"); //将下标0是wangwu修改为likedx
        System.out.println(likedx); //查看修改前的数据

        //查询数据
        Object o = arr.get(0);
        System.out.println(o);

        System.out.println(arr);

        //集合转换数组
        Object[] objects = arr.toArray();

        //数组转换集合
        List<Object> objects1 = Arrays.asList(objects);

        System.out.println("*************************");
        //遍历集合方式一:普通遍历
/*       for (int i = 0; i < arr.size(); i++) {
            System.out.println(arr.get(i));
        }*/

        //方式二:增强for
  /*      for (Object obj : arr) {
            System.out.println(obj);
        }*/

        //方式三:iterator迭代器
        Iterator iterator = arr.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}
package Test1;

public class Cat {
    private String name;

    public Cat() {
    }

    public Cat(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                '}';
    }
}
public class ArrayTest {
    public static void main(String[] args) {
        List list = new ArrayList();

        //添加4只小猫
        list.add(new Cat("英短猫"));
        list.add(new Cat("缅因猫"));
        list.add(new Cat("布偶猫"));
        list.add(new Cat("狸花猫"));


        //查询有几只小猫
        System.out.println("小猫数量:" + list.size()); //4

        //删除小猫
        list.remove(0);

        System.out.println("小猫数量:" + list.size()); //3

        //遍历小猫
        for (int i = 0; i < list.size(); i++) {
            //向下转型
            Cat cat = (Cat) list.get(i);
            System.out.print(cat.getName() + "\t"); //缅因猫  布偶猫    狸花猫
        }

        System.out.println("");

        //修改小猫
        list.set(0,new Cat("蓝猫"));
        System.out.println("修改的小猫为:");
        for (int i = 0; i < list.size(); i++) {
            //向下转型
            Cat cat = (Cat) list.get(i);
            System.out.println(cat.getName()); //蓝猫    布偶猫    狸花猫
        }
        
    }
}

ArrayList底层原理

  • JDK1.7:

    • ArrayList arr = new ArrayList(); //底层创建了长度是10的Object[]数组elementData
    • 如果elementData数组容量不够 那就扩容 默认情况下扩容为原来的1.5倍,同时需要将原有数组中的数据复制到新的数组中
  • JDK1.8:

    • ArrayList arr = new ArrayList(); //底层Object[]elementData初始化为0 没有创建长度
    • arr.add(1); //第一次调用add时 底层才创建了长度10的数组,并将数据添加到elementData
    • 如果elementData数组容量不够 那就扩容 默认情况下扩容为原来的1.5倍,同时需要将原有数组中的数据复制到新的数组中

LinkedList集合

特点:

  1. 底层使用双向链表存储
  2. 线程不安全
  3. 频繁的插入 删除 使用此类的效率比ArrayList高
  4. 可以包含重复的元素
方法说明
getFirst获取头部信息
getLast获取尾部信息
addFirst指定头部添加信息
addLast指定尾部添加信息
remove默认删除第一个
removeFirst删除头部信息
removeLast删除尾部信息
push(Object e)添加数据
pop弹出数据
public class Linkedlist_Test {
    public static void main(String[] args) {
        LinkedList list = new LinkedList();
        //增删改查也比较重要 用法一样

        //方式一: 入栈
        list.add(1);
        list.add(2);
        list.add(3);
        System.out.println(list);

        //弹栈
        System.out.println(list.pop());
        System.out.println(list.pop());
        System.out.println(list.pop());

        //栈空了会 报错 NoSuchElementException
        //System.out.println(list.pop());

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

        //方式二:入栈  先进后出 因在尾部last
        list.addLast(1);
        list.addLast(2);
        list.addLast(3);

        //弹栈
        System.out.println(list.removeLast());
        System.out.println(list.removeLast());
        System.out.println(list.removeLast());
        //栈空了会 报错 NoSuchElementException
        //System.out.println(list.removeLast());
    }
}

Set集合

特点:

  1. 存储无序的 不可重复的数据
  2. Set的常用实现类有:HashSet、TreeSet、LinkedHashSet。
  3. Set集合支持的遍历方式和Collection集合一样:foreach和Iterator。
  4. 向set中添加数据,所有的类一定要重写hashCode和equals实现去重

HashSet

  1. 无序性 存储的数据在底层数组中并非按照数组的索引顺序添加 而是根据数据的哈希值添加的
  2. Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
  3. 作为Set主要实现类 线程不安全的 可以存储NULL值

注意

HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。因此,存储到HashSet的元素要重写hashCode和equals方法。

package Collection;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;

public class SetTest {
    public static void main(String[] args) {
        Set set = new HashSet();
        set.add(122);
        set.add("AA");
        set.add("BB");
        set.add("CC");
        set.add(456);
        set.add(123);
        set.add(new User1("张三",10));
        set.add(new User1("张三",10));    

        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }


    }
}
class User1{
    private String name;
    private int age;

    public User1() {
    }

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

    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 String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

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

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

LinkedHashSet

特点:

  1. LinkedHashSet作为HashSet的子类 在添加数据的同时 每个数据还维护了两个引用(两个引用指前和后) 记录当前数据前一个数据和后一个数据
  2. 频繁遍历 效率高 有序不可重复
package Collection;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

public class SetTest02 {
    public static void main(String[] args) {
        Set set = new LinkedHashSet();
        set.add("zhang");
        set.add(123);
        set.add(4521);
        set.add("lisi");
        set.add("wangwu");
        set.add("wangwu");
        System.out.println("元素的个数为:" + set.size());

        for (Object obj : set) {
            System.out.println(obj);
        }
    }
}

TreeSet

特点:

  1. 不允许重复
  2. 实现排序
  3. 自然排序或定制排序
  4. 如果使用的是自然排序,则通过调用实现的compareTo方法
  5. 如果使用的是定制排序,则通过调用比较器的compare方法
  • 如何实现去重的?

    • 如果使用的是自然排序,则通过调用实现的compareTo方法
    • 如果使用的是定制排序,则通过调用比较器的compare方法
  • 如何排序?

    • 方式一:自然排序

      • 实现Comparable接口并重写compareTo方法
    • 方式二:定制排序

      • 实现Comparator接口,重写compare方法

自然排序

  • 根据姓名进行自然排序
public class TreeSet_Test05 {
    public static void main(String[] args) {
        Set<Animal> set = new TreeSet<>();
        set.add(new Animal("asd"));
        set.add(new Animal("vxc"));
        set.add(new Animal("bdfa"));
        set.add(new Animal("zwedsa"));

        Iterator<Animal> iterator = set.iterator();
        while (iterator.hasNext()) {
            Animal next = iterator.next();
            System.out.println(next);
        }
    }
}
class Animal implements Comparable<Animal>{
    private String name;

    public Animal() {
    }

    public Animal(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

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

    @Override
    public int compareTo(Animal o) {
        //升序
        return this.name.compareTo(o.name);
        
        //降序
        //return -this.name.compareTo(o.name);
    }
}
  • 假设我们有一个类 cat,它包含两个属性:nameage。我们想要按照年龄进行排序:

    • cat类需要实现Comparable并且重写compareTo方法
public class TreeSet_Test04 {
    public static void main(String[] args) {
        Set<Cat> set = new TreeSet<>();
        set.add(new Cat("狸花猫",1));
        set.add(new Cat("蓝猫",3));
        set.add(new Cat("博美",2));

        Iterator<Cat> iterator = set.iterator();
        while (iterator.hasNext()) {
            Cat next = iterator.next();
            System.out.println(next);
        }

    }
}
class Cat implements Comparable<Cat>{
    private String name;
    private int age;

    public Cat() {
    }

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

    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 String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Cat o) {
        //根据年龄从高到低进行排序
        //return -Integer.compare(age,o.age);

        //根据年龄从低到高进行排序
        return Integer.compare(this.age,o.age);
    }
}

定制排序

  • 根据字符串长度进行排序

    • 向set添加数据时其指定类需要实现Comparator接口并重写compare方法
public class StringLengthComparator implements Comparator<String> {

    //实现Comparator并重写compare方法
    @Override
    public int compare(String o1, String o2) {
        return Integer.compare(o1.length(),o2.length());
    }
}
public class TreeSet_Test {
    public static void main(String[] args) {
        //在使用TreeSet时将StringLengthComparator传递给他的构造参数
        //根据字符串的长度进行升序排序
        Set set = new TreeSet(new StringLengthComparator());
        set.add("a123");
        set.add("a");
        set.add("bcdfg");
        set.add("12");
        set.add("b123"); //只会按照插入的顺序进行排序


        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println(next);
            //a a12 a123 bcdfg
        }
    }
}
  • 假设我们有一个 Student 类,包含 namescore 两个属性。现在要按照学生分数从高到低排序:

    • 学生类需要重写tostring方法
    • 分数排序类需要实现implements接口并且实现compare方法
    public class TreeSet_Test02 {
        public static void main(String[] args) {
            //创建TreeSet的时候传入ScoreComparator构造方法
            Set<Student> set = new TreeSet<>(new ScoreComparator());
            set.add(new Student("张三",85));
            set.add(new Student("李四",78));
            set.add(new Student("王五",90));
            set.add(new Student("赵六",88));
    
            Iterator<Student> iterator = set.iterator();
            while (iterator.hasNext()) {
                Student next = iterator.next();
                System.out.println(next);
                //Student{name='李四', score=78}
                //Student{name='张三', score=85}
                //Student{name='赵六', score=88}
                //Student{name='王五', score=90}
            }
        }
    }
    class Student{
        private String name;
        private int score;
    
        public Student() {
        }
    
        public Student(String name, int score) {
            this.name = name;
            this.score = score;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getScore() {
            return score;
        }
    
        public void setScore(int score) {
            this.score = score;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", score=" + score +
                    '}';
        }
    }
    //分数排序类 实现了Comparator接口
    class ScoreComparator implements Comparator<Student>{
        @Override
        public int compare(Student o1, Student o2) {
            //从高到低
            //return -Integer.compare(o1.getScore(),o2.getScore());
    
            //从低到高
            return Integer.compare(o1.getScore(),o2.getScore());
        }
    }

组合排序

  • 假设我们有一个 Person 类,包含 nameage 两个属性。我们想要按照年龄升序排序,如果年龄相同,则按照名字升序排序

    • 年龄类实现Comparator接口重写compare方法对其进行排序
public class TreeSet_Test03 {
    public static void main(String[] args) {
        Set<Person> set = new TreeSet<>(new AgeNameComparator());
        set.add(new Person("阿乐",85));
        set.add(new Person("李四",96));
        set.add(new Person("王五",70));
        set.add(new Person("张三",85));


        Iterator<Person> iterator = set.iterator();
        while (iterator.hasNext()) {
            Person next = iterator.next();
            System.out.println(next);
        }

    }
}
class Person{
    private String name;
    private int age;

    public Person() {
    }

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

    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 String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

class AgeNameComparator implements Comparator<Person> {

    @Override
    public int compare(Person o1, Person o2) {
        int result = Integer.compare(o1.getAge(),o2.getAge());
        if (result == 0){
            return o1.getName().compareTo(o2.getName());
        }
        return result;
    }
}

Map集合

特点:

  1. Map和Collection没有继承关系
  2. Map集合是以Key和Value的方式存储数据 键值对
  3. map中的集合,元素是成对儿存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值

Map常用方法

属性说明
put(Object key,Object value)添加数据
putAll(Map m)添加对儿新集合
clear()清空集合中的数据
remove(Object key)通过key删除数据
get(Object key)通过key获取value
containsKey(Object key)判断是否包含某个key(键)
containsValue(Object value)判断是否包含某个value(值)
isEmpty()判断是否为空
keySet()获取map所有的key 也可以讲key转换为一个集合
size()获取键值对的个数
entrySet()将Map集合转换为Set集合
values()获取所有的value
Map.Entry表示集合中的一个对象的实体key-value
public class Map_Test {
    public static void main(String[] args) {
        //创建Map集合对象
        Map<Integer,String> map = new HashMap<>();

        //向Map集合中添加对象
        map.put(1,"zhangsan");
        map.put(2,"lisi");
        map.put(3,"wangwu");
        map.put(4,"zhaoliu");

        //通过key删除数据
        map.remove(1);

        //判断是否包含某个key
        System.out.println(map.containsKey(2));

        //判断是否包含某个value
        System.out.println(map.containsValue("wangwu"));

        //通过key获取value
        System.out.println(map.get(2));

        //获取键值对的数量
        System.out.println(map.size());

        //获取所有的value
        Collection<String> values = map.values();
        //遍历value
        for (String s : values) {
            System.out.println(s);
        }
        
        //清空集合
        //map.clear();
    }
}

Map集合的遍历

基本:

将map转换为set集合 通过node进行遍历 Set<Map.Entry<K, V>> set = map.entrySet(); 效率高

通过set集合遍历key

public class Map_Test {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put(1,"zhangsan");
        map.put(2,"lisi");
        map.put(3,"wangwu");
        map.put(4,"zhaoliu");

        //方式一 迭代器遍历Key
        Set keys = map.keySet();
        Iterator iterator = keys.iterator();
        while (iterator.hasNext()){
            System.out.println("Key的值是:" + iterator.next());
        }

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

        //方式二 增强for
        Set keys1 = map.keySet();
        for (Object obj : keys1) {
            System.out.println("Key的值是:" + obj);
        }

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

通过key遍历value

public class Map_Test02 {
    public static void main(String[] args) {
        Map  map = new HashMap();
        map.put(1,"zhangsan");
        map.put(2,"lisi");
        map.put(3,"wangwu");

        //遍历value
        Set keys = map.keySet();
        Iterator iterator = keys.iterator();
        while (iterator.hasNext()){
            Object key = iterator.next();
            System.out.println("value的值为:" + map.get(key));
        }

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

        //增强for
        Set set1 = map.keySet();
        for (Object value : set1) {
            System.out.println("value的值为:" + map.get(value));
        }
        System.out.println("====================");

        //方式二
        Collection values = map.values();
        for (Object value : values){
            System.out.println("value的值为:" + value);
        }
    }
}

遍历集合

例:

public class Map_Test03 {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put(1,"zhangsan");
        map.put(2,"lisi");
        map.put(3,"wangwu");
        map.put(4,"zhaoliu");

        //迭代器遍历集合
        Set set = map.entrySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            Object obj = iterator.next();
            Map.Entry entry = (Map.Entry)obj;
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
        System.out.println("=================");

        //增强for
        Set keys = map.entrySet();
        for (Object obj : keys) {
            Map.Entry entry = (Map.Entry)obj;
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
    }
}

例:

public class Map_Test04 {
    //效率高
    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap<>();
        map.put(1,"张三");
        map.put(2,"王五");
        map.put(3,"赵六");

        //将map集合转换为set集合 通过迭代器方式进行遍历
        //将map集合转换为set集合
        Set<Map.Entry<Integer, String>> entries = map.entrySet();
        //创建一个迭代器对象
        Iterator<Map.Entry<Integer, String>> iterator = entries.iterator();
        while (iterator.hasNext()){
            //每一次取出node 通过node访问key和value
            Map.Entry<Integer, String> node = iterator.next();
            System.out.println(node.getKey() + "="  + node.getValue());
        }

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

        //增强for
        //将map集合转换为set集合
        Set<Map.Entry<Integer, String>> entries1 = map.entrySet();
        for (Map.Entry<Integer,String> key : entries1) {
            System.out.println(key.getKey() + "=" + key.getValue());
        }
    }
}

HashMap底层实现原理

  • JDK1.7:

    • 实例化后 底层创建了长度是16的一维数组Entry[]数组
    • map.put(key1,value1):调用key1的HachCode()计算哈希值,得到在Entry数组中的存放位置
    • 如果此位置上数据为空 则k1v1添加成功

      • 如果不为空 比较key1和已经存在的一个或者多个数据的哈希值

        • 如果key1的哈希值和已经存在数据的哈希值不相同 则添加成功
        • 如果key1的哈希值和已经存在的某一个数据的哈希值相同 调用key1所在类的equals(key2)方法比较

          • 如果equals()为false:则添加成功
          • 如果为true:使用value1替换value2
    • 扩容方式:扩容为原来容量的2倍,并将原有数据复制过来
  • JDK1.8:

    • 实例化后 底层没有创建一个长度为16的一维数组Node[]数组
    • 首次调用put方法时 底层创建长度为16的数组
    • JDK7底层结构:数组+链表
    • JDK8底层结构:数组+链表+红黑树
    • 当数组的某一个索引位置上的元素以链表形式存在的数据个数>8 并且当前数组长度>64 此时此索引位置上的所有数据改为使用红黑树存储
  • HashMap和TreeMap有什么区别

    • HashMap的key可以为null、TreeMap不可以

Properties属性类

Properties是一个Map集合,Hashtable的子类

Properties的key和value都是String类型

Properties被称为属性类对象 一般用来处理配置文件

属性说明
setProperty(String key,String value)添加元素
getProperty(String key)通过key获取value
public class Properties_Test {
    //Properties:常用来处理配置文件。key和value都是String类型
    public static void main(String[] args) {

        Properties pro = new Properties();

        pro.setProperty("url","blogdx.com");
        pro.setProperty("username","root");
        pro.setProperty("password","123");

        //通过key获取value
        String url = pro.getProperty("url");
        System.out.println(url);
        
        System.out.println(pro.getProperty("username"));
        System.out.println(pro.getProperty("password"));
    }
}

Collections工具类

Collections是一个操作Set、List和Map等集合的工具类

Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法

静态属性说明
reverse翻转list
shuffle随机排序
sort自然排序
swap(list,int i,intj)交换list集合中指定索引位置上的两个元素
max获取最大值
min获取最小值
frequency(Object o)获取list集合中元素出现的次数
synchronizedList将list集合转换为线程安全的
public class Collections_Test {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(123);
        list.add(123);
        list.add(23);
        list.add(-13);
        list.add(0);
        list.add(89);


        //翻转list中元素的顺序
        Collections.reverse(list);

        //对list集合元素进行随机排序
        Collections.shuffle(list);

        //对list进行自然排序
        Collections.sort(list);


        //交换list集合中指定索引位置上的两个元素
        Collections.swap(list,0,1);

        //获取最大值
        //System.out.println(Collections.max(list));

        //获取最小值
        //System.out.println(Collections.min(list));

        //获取list集合中123出现的次数
        int frequency = Collections.frequency(list, 123);

        //synchronizedList:将list转换为线程安全的
        List list1 = Collections.synchronizedList(list);
        System.out.println(list1);
    }
}

斗地主小游戏

package Demo2;

import java.util.*;

public class DouDiZhu {
    public static void main(String[] args) {
        // 初始化一副牌
        List<String> poker = initPoker();
        // 洗牌
        Collections.shuffle(poker);
        // 发牌
        Map<Integer, List<String>> players = dealCards(poker);
        // 显示手牌
        showCards(players);
    }

    /**
     * 初始化一副牌
     */
    private static List<String> initPoker() {
        List<String> poker = new ArrayList<>();
        String[] colors = {"♠", "♥", "♣", "♦"};
        String[] numbers = {"2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3"};
        for (String color : colors) {
            for (String number : numbers) {
                poker.add(color + number);
            }
        }
        poker.add("小王");
        poker.add("大王");
        return poker;
    }

    /**
     * 发牌
     */
    private static Map<Integer, List<String>> dealCards(List<String> poker) {
        Map<Integer, List<String>> players = new HashMap<>();
        // 底牌
        List<String> bottom = new ArrayList<>();
        // 发牌
        for (int i = 0; i < poker.size(); i++) {
            String card = poker.get(i);
            if (i >= poker.size() - 3) { // 最后三张为底牌
                bottom.add(card);
            } else {
                int playerNum = i % 3 + 1; // 玩家编号
                List<String> playerCards = players.computeIfAbsent(playerNum, k -> new ArrayList<>());
                playerCards.add(card);
            }
        }
        players.put(0, bottom);
        return players;
    }

    /**
     * 显示手牌
     */
    private static void showCards(Map<Integer, List<String>> players) {
        for (Map.Entry<Integer, List<String>> entry : players.entrySet()) {
            Integer key = entry.getKey();
            List<String> value = entry.getValue();
            System.out.print("玩家" + key + ": ");
            for (String s : value) {
                System.out.print(s + " ");
            }
            System.out.println();
        }
    }
}
  1. initPoker() 方法用于初始化一副扑克牌,包括52张普通牌和2张大小王,返回一个列表对象;
  2. dealCards() 方法接收一副已经初始化好的扑克牌,首先创建一个 HashMap 对象来存储三个玩家的手牌和三张底牌。之后通过循环遍历牌堆,将前51张牌均分给三个玩家,每个玩家17张牌。最后将最后三张牌作为底牌放入 bottom 列表中,并将 bottom 列表也放入 players 中,编号为0表示底牌;
  3. showCards() 方法用于展示每个玩家的手牌和三张底牌。遍历 players,对于每个键值对,输出玩家编号和对应的牌。
  4. main 方法中,首先调用 initPoker() 方法来初始化一副牌,然后使用 Collections.shuffle() 方法洗牌,再调用 dealCards() 方法发牌,最后使用 showCards() 方法展示每个玩家的手牌和三张底牌。
最后修改:2023 年 03 月 29 日
如果觉得我的文章对你有用,请随意赞赏