Java高级(一)集合

本文深入解析Java集合类如List, Set, Map, Iterator和泛型的使用,包括ArrayList, LinkedList, HashSet, LinkedHashSet, HashMap,及JDK9优化等内容,以斗地主为例演示数据组织与操作。
摘要由CSDN通过智能技术生成

目录

集合

Collection类

Iterator迭代器

泛型

含有泛型的类

含有泛型的方法

含有泛型的接口

泛型通配符(修饰在在方法的形参上)

 Collections类:集合工具类

综合案例:斗地主

List集合

ArrayList集合

LinkedList集合

Set集合

HashSet集合(不能保证 存入、取出的顺序相同)

LinkedHashSet集合

可变参数(已知参数类型,不确定参数个数时可以使用)

设置比较规则

自然排序:实现Comparable接口

定义比较器(通常使用匿名内部类来实现)

自然排序与比较器的区别:

 Map集合(双列集合)

Map接口的常用方法

Map集合的遍历方法:

HashMap集合

LinkedHashMap集合

JDK9对集合添加的优化

综合案例:斗地主


​​​​​​​

集合

集合是java中提供的一种容器,可以用来存储多个数据。

集合和数组的区别:

  • 数组的长度是固定的。集合的长度是可变的。
  • 数组存储的是同一类型的数据(基本数据类型、引用数据类型),集合存储的都是对象(对象的类型可以不一致)

集合框架

 List接口的特点:元素有序、元素可重复、有索引

Set接口的特点:元素无序、元素不可重复、无索引(没有索引,不能使用普通for循环遍历)

Collection类

Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法。

  • public boolean add(E e):把给定的对象添加到当前集合中
  • public void clear():清空集合中所有的元素
  • public boolean remove(E e):把给定的对象在当前集合中删除
  • public boolean contains(E e):判断当前集合中是否包含给定的对象
  • public boolean isEmpty():判断当前集合是否为空
  • public int size():返回集合中元素的个数
  • public Object[] toArray():把集合中的元素,存储到数组中

示例代码:

 public static void main(String[] args) {
        Collection<String> collection=new ArrayList<>();
        //添加元素
        collection.add("A"); collection.add("B");collection.add("C");collection.add("D");
        System.out.println(collection);//[A, B, C, D]
        collection.remove("A");//删除"A"这个对象
        System.out.println(collection);//[B, C, D]
        System.out.println(collection.isEmpty());//集合不为空 返回false
        System.out.println(collection.contains("B"));//集合包含"B"对象,返回true
        System.out.println(collection.size());//集合的长度为3
        Object[] objects = collection.toArray();//将集合转换成对象数组
        for (Object object : objects) {
            System.out.print(object+"\t");//B	C	D	
        }
        System.out.println();
        collection.clear();//清空集合
        System.out.println(collection);//[]
    }

Iterator迭代器

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

获取迭代器的方法:public Iterator iterator()  获取集合对应的迭代器

Iterator接口的常用方法:

  • public E next() :返回迭代的下一个元素(两个动作:先返回下一个元素,再向后移动指针)
  • public boolean hasNext():如果仍有元素可以迭代,则返回 true

Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素

增强for(for each)

专门用来遍历数组、集合,内部原理其实是一个Iterator迭代器。在遍历过程中,不能对元素进行增删操作

示例代码:

 public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("张三");list.add("李四");list.add("王五");
        //迭代器方法实现遍历
            //while形式
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.print(iterator.next()+'\t');//张三	李四	王五	
        }
        System.out.println();
            //for形式
        for(Iterator<String> iterator1=list.iterator();iterator1.hasNext();){
            System.out.print(iterator1.next()+'\t');张三	李四	王五	
        }
        System.out.println();
        //for each遍历集合
        for (String s : list) {
            System.out.print(s+'\t');张三	李四	王五	
        }
    }

泛型

可以在类或方法中预支地使用未知的类型,当没有指定泛型时,默认类型为Object类型。

泛型的好处:

  • 避免了类型转换
  • 把运行期异常提升到了编译期

含有泛型的类

public class test1 <E>{
    private E mvp;
    public E getMvp() {
        return mvp;
    }
    public void setMvp(E mvp) {
        this.mvp = mvp;
    }
}

         在创建对象的时候确定泛型

含有泛型的方法

public <E> void show(E e){
        System.out.println(e);
    }

        调用方法时确定泛型

含有泛型的接口

public interface test3 <E>{
        E getArray(E e);
}
  •  在实现类中确定泛型
public class impl2 implements test3<String>{
    @Override
    public String getArray(String s) {
        return s;
    }
}
  • 在创建对象时确定泛型
public class test3impl1<E> implements test3 <E>{
    @Override
    public E getArray(E e) {
         return e;
    }
}

泛型通配符(修饰在在方法的形参上)

不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符。

  public static void test(ArrayList<?>list){
        Iterator<?> iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

        方法功能:可以遍历各种类型的ArrayList

高级使用:

// 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
public static void getElement1(Collection<? extends Number> coll){}
// 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
public static void getElement2(Collection<? super Number> coll){}

 Collections类:集合工具类

  •  Collections.sort(list)  :将集合升序
  •  Collections.reverse(list):将集合反转
  •  Collections.shuffle(list):将集合乱序

综合案例:斗地主

public static void main(String[] args) {
        ArrayList<String> list_1 = new ArrayList<>();//存储花色
        ArrayList<String> list_2 = new ArrayList<>();//存储数字
        ArrayList<String> list_3 = new ArrayList<>();//存储牌面
        ArrayList<String> player1 = new ArrayList<>();//玩家一
        ArrayList<String> player2 = new ArrayList<>();//玩家二
        ArrayList<String> player3 = new ArrayList<>();//玩家三
        ArrayList<String> dipai = new ArrayList<>();//底牌
        list_1.add("♠");list_1.add("♥");list_1.add("♣");list_1.add("♦");
        for (int i = 2; i <11 ; i++) {
            list_2.add(i+"");
        }
        list_2.add("J"); list_2.add("Q"); list_2.add("K"); list_2.add("A");
        for(String a:list_1){
            for(String b:list_2){
                list_3.add(a+b);
            }
        }
        list_3.add("大王");list_3.add("小王");
        Collections.shuffle(list_3);
        for(int i=0;i<list_3.size();i++){
            if(i>=50){
                dipai.add(list_3.get(i));
            }else {
                if(i%3==0){
                    player1.add(list_3.get(i));
                }else if(i%3==1){
                    player2.add(list_3.get(i));
                }else {
                   player3.add(list_3.get(i));
                }
            }
        }
        System.out.println("斗地主游戏");
        System.out.println("玩家一:"+player1);
        System.out.println("玩家二:"+player2);
        System.out.println("玩家三:"+player3);
        System.out.println("底牌:"+dipai);
    }

List集合

特点:

  • 它是一个元素存取有序的集合
  • 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素
  • 集合中可以有重复的元素

List接口的常用方法(根据索引来操作集合)

  • public void add(int index, E element):将指定的元素,添加到该集合中的指定位置上
  • public E get(int index):返回集合中指定位置的元素
  • public E remove(int index):移除列表中指定位置的元素, 返回的是被移除的元素
  • public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素
public static void main(String[] args) {
        List<String> list=new ArrayList<>();
        list.add("张三");list.add("李四");list.add("王五");
        list.add(1,"钱二");//将元素添加到第二个位置上
        System.out.println(list);//[张三, 钱二, 李四, 王五]
        list.set(1,"赵六");//修改元素
        System.out.println(list);//[张三, 赵六, 李四, 王五]
        list.remove(0);//删除元素
        System.out.println(list);//[赵六, 李四, 王五]
        for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i)+"\t");//赵六	李四	王五
        }
    }

ArrayList集合

集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合。

LinkedList集合

集合数据存储的结构是链表结构。方便元素添加、删除的集合

  • public void addFirst(E e):将指定元素插入此列表的开头。
  • public void addLast(E e):将指定元素添加到此列表的结尾(和add()功能相同)
  • public E getFirst():返回此列表的第一个元素。
  • public E getLast():返回此列表的最后一个元素
  • public E removeFirst():移除并返回此列表的第一个元素
  • public E removeLast():移除并返回此列表的最后一个元素
  • public E pop():从此列表所表示的堆栈处弹出一个元素(和removeFirst()功能相同)
  • public void push(E e):将元素推入此列表所表示的堆栈(和addFirst(E e)功能相同)
public static void main(String[] args) {
        LinkedList<String> list1 = new LinkedList<>();
        list1.add("a");
        list1.addFirst("b");
        list1.push("c");
        list1.addLast("d");
        System.out.println(list1);//[c, b, a, d]
        list1.removeFirst();
        list1.removeLast();
        list1.pop();
        System.out.println(list1);//[a]
    }

Set集合

Set集合的特点:无序、不能重复、没有索引

HashSet集合(不能保证 存入、取出的顺序相同)

是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashCode与equals方法。

保证HashSet集合的唯一性:

  1. 通过hashCode方法,获取哈希值
  2. 根据哈希值计算存储位置,哈希值%表长(默认值16)
  3. 该位置有无元素存在,如果没有元素,就将元素存储在该位置
  4. 如果位置上有元素,遍历该位置的所有元素,比较哈希值是否相同,如果不同则将元素存储在该位置
  5. 如果哈希值相同,调用equals方法比较对象内容是否相等,如果不相等则将元素存储在该位置
  6. 如果相等,元素重复,不存储

给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一

定义Student类 成员属性name、age,重写hashCode和equals

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

在main进行测试:

public static void main(String[] args) {
        HashSet<Student> hashSet = new HashSet<>();
        hashSet.add(new Student("张三",23));
        hashSet.add(new Student("李四",12));
        hashSet.add(new Student("王五",23));
        hashSet.add(new Student("王五",23));//添加重复元素
        for (Student student : hashSet) {
            System.out.print(student);//Student{name='张三', age=23}Student{name='王五', age=23}Student{name='李四', age=12}

        }
    }

LinkedHashSet集合

它是链表和哈希表组合的一个数据存储结构。链表保证元素有序,哈希表保证元素唯一

  1. public static void main(String[] args) {
            LinkedHashSet<Student> hashSet = new LinkedHashSet<>();
            hashSet.add(new Student("张三",23));
            hashSet.add(new Student("李四",12));
            hashSet.add(new Student("王五",23));
            hashSet.add(new Student("王五",23));//添加重复元素
            for (Student student : hashSet) {
                System.out.print(student);//Student{name='张三', age=23}Student{name='李四', age=12}Student{name='王五', age=23}
    
            }
        }

可变参数(已知参数类型,不确定参数个数时可以使用)

同样是代表数组,但是在调用这个带有可变参数的方法时,不用创建数组

如果在方法书写时,这个方法拥有多参数,参数中包含可变参数,可变参数一定要写在参数列表的末尾位置。

 public static void main(String[] args) {
        System.out.println(sum(1,2,3));//6
        System.out.println(sum(2,3,4,5));//14
    }
    public static int sum(int...a){
        int sum=0;
        for (int i : a) {
            sum+=i;
        }
        return sum;
    }

设置比较规则

自然排序:实现Comparable接口

  1. 自定义类实现Comparable接口
  2. 重写compareTo()

为Student重写compareTo()方法

 @Override
    public int compareTo(Student student) {
        int num = this.age - student.getAge();//主条件相同时,需要设置次条件
        return num==0?this.name.compareTo(student.getName()):num;
    }

定义比较器(通常使用匿名内部类来实现)

  1. 自定义类实现Comparator接口
  2. 重写Compare方法
 Collections.sort(students, new Comparator<Student>() {
           @Override
           public int compare(Student student, Student t1) {
               int num=student.getAge()-t1.getAge();
               return num==0?student.getName().compareTo(t1.getName()):num;
           }
       });

补充:Collections.sort方法需要借助比较规则来完成

自然排序与比较器的区别:

  1. 比较器是一个独立的比较规则(类似于一个第三方的工具)
  2. 如果自然排序和比较器都存在,以比较器为主

 Map集合(双列集合)

存储方式为键值对

特点:键不能重复,值可以重复。每一个键只能对应一个值

Map接口的常用方法

  • public V put(K key, V value) : 把指定的键与指定的值添加到Map集合中
  • public V remove(Object key) : 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
  • public V get(Object key) 根据指定的键,在Map集合中获取对应的值
  • public Set<K> keySet() : 获取Map集合中所有的键,存储到Set集合中
  • public Set<Map.Entry<K,V>> entrySet() : 获取到Map集合中所有的键值对对象的集合(Set集合)

示例代码:

public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        //添加元素
        map.put("001","张三");map.put("002","李四"); map.put("003","王五");
        map.put("004","赵六");map.put("004","钱二");//添加元素时,key值相同时,value会被替代
        System.out.println(map);//{001=张三, 002=李四, 003=王五, 004=钱二}
        map.remove("003");//删除元素
        System.out.println(map);//{001=张三, 002=李四, 004=钱二}
        System.out.println(map.get("001"));//根据键获得指定元素
    }

Map集合的遍历方法:

        1、键找值的方式

   Set<String> keySet = map.keySet();
        for (String key : keySet) {
            String value = map.get(key);
            System.out.println(key+"======"+value);
        }

         2、遍历键值对的方式

 Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            System.out.println(entry.getKey()+"====="+entry.getValue());
        }

Entry是键值对对象

HashMap集合

特点:无序,存入和取出的顺序可能不一样

存储自定义类型键值:当给HashMap中存放自定义对象时,如果自定义对象作为key存在,这时要保证对象唯一,必须复写对象的hashCode和equals方法

LinkedHashMap集合

它是链表和哈希表组合的一个数据存储结构

特点:存入和取出的顺序一样

JDK9对集合添加的优化

        of()方法只是Map,List,Set这三个接口的静态方法,其父类接口和子类实现并没有这类方法,比如
HashSet,ArrayList等待;返回的集合是不可变的;

 List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 2);//[1, 2, 3, 4, 5, 6, 2]
 Set<Integer> integers = Set.of(1, 2, 3, 4, 5, 6);//[2, 1, 6, 5, 4, 3]
 Map<Integer, String> map1 = Map.of(1, "a", 2, "b");//{2=b, 1=a}

综合案例:斗地主

        案例分析:花色、数字存放在list中,map存放编号和牌面(花色+数字),获取map的编号集合,将其打乱,分发给4个集合;通过分发的编号 获得相应的牌面

 public static void main(String[] args) {
        ArrayList<String> list_1 = new ArrayList<>();//花色
        ArrayList<String> list_2 = new ArrayList<>();//数字
        HashMap<Integer, String> hashMap = new HashMap<>();//编号:牌面
        ArrayList<Integer> list = new ArrayList<>();//编号打乱
        ArrayList<Integer> nlist_1 = new ArrayList<>();//分发编号
        ArrayList<Integer> nlist_2 = new ArrayList<>();
        ArrayList<Integer> nlist_3 = new ArrayList<>();
        ArrayList<Integer> nlist_4 = new ArrayList<>();
        ArrayList<String> player1 = new ArrayList<>();//牌面
        ArrayList<String> player2 = new ArrayList<>();
        ArrayList<String> player3 = new ArrayList<>();
        ArrayList<String> dipai = new ArrayList<>();
        Collections.addAll(list_1,"♠","♥","♦","♣");
        Collections.addAll(list_2,"A","2","3","4","5","6","7","8","9","10","J","Q","K");
        int count=1;
        hashMap.put(count++,"大王");
        hashMap.put(count++,"小王");
        for (String s : list_1) {
            for (String s1 : list_2) {
                hashMap.put(count++,s+s1);
            }
        }
        Set<Integer> keySet = hashMap.keySet();
        list.addAll(keySet);
        Collections.shuffle(list);
        for (int i = 0; i < list.size(); i++) {
            if (i>50){
                nlist_4.add(list.get(i));
            }else if(i%3==0){
                nlist_1.add(list.get(i));
            }else if(i%3==1){
                nlist_2.add(list.get(i));
            }else{
                nlist_3.add(list.get(i));
            }
        }
        for (Integer integer : nlist_1) {
            player1.add(hashMap.get(integer));
        }
        for (Integer integer : nlist_2) {
            player2.add(hashMap.get(integer));
        }
        for (Integer integer : nlist_3) {
            player3.add(hashMap.get(integer));
        }
        for (Integer integer : nlist_4) {
            dipai.add(hashMap.get(integer));
        }
        System.out.println("斗地主游戏");
        System.out.println("玩家一:"+player1);
        System.out.println("玩家二:"+player2);
        System.out.println("玩家三:"+player3);
        System.out.println("底牌:"+dipai);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值