java入门篇11 --- 集合

无论什么语言,集合应当是我们最常用的一种类型啦,大体上分为有序列表、map、sey、队列

首先先来看一下有序列表,

List内部跟数组一样也是按照先后顺序排放的,但对于增删,非常方便,list的实现大多是使用ArrayList实现的,先来看一下List的源码,这里面有一个<E>,这个就是泛型,java是面向对象语言,他在运行期间,才会将我们的类进行初始化,因此,就利用这一特性,我们输入指定的引用类型,注意必须是引用类型,基本类型不是类,JVM在编译是,会把它当作object,然后再运行期间就会帮我们转化为指定的类型

// 一个接口
public interface List<E> extends Collection<E> {
    int size();  // 大小
    boolean isEmpty();  // 是否为空
    boolean contains(Object o);  // 是否包含
    Iterator<E> iterator();  // 是否可迭代
    Object[] toArray();  // 转化为数组,返回就是object[]
    <T> T[] toArray(T[] a);  // 转化为数组,返回就是指定的类型[]
    boolean add(E e);  // 增加,返回true,false
    boolean remove(Object o);  // 删除,返回bollean
    boolean containsAll(Collection<?> c);  // 包含
    boolean addAll(Collection<? extends E> c);// 添加
    boolean addAll(int index, Collection<? extends E> c);  // 添加指定位置
    boolean removeAll(Collection<?> c);  // 删除
    @SuppressWarnings({"unchecked", "rawtypes"})
    default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }  // 拍讯,因此想要排序,必须实现Comparator接口
    void clear(); // 情况
    boolean equals(Object o);  // 判断是否相等
    int hashCode();  // 获取这个code, 返回值int
    E get(int index);// 获取指定下表的对象
    E set(int index, E element);// 重置
    void add(int index, E element);  // 添加
    E remove(int index);  // 删除
    int indexOf(Object o);  // 获取某个对象的下表
    int lastIndexOf(Object o);  // 获取最后一个对象的下表
    @SuppressWarnings("unchecked")  // 这个传入为空,就会报错
    static <E> java.util.List<E> of() {
        return (java.util.List<E>) ImmutableCollections.ListN.EMPTY_LIST;
    }
    static <E> java.util.List<E> of(E e1, E e2, E e3, E e4, E e5) {  // 初始化指定的列表
        return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5);
    }
}

那么,我们来看一下上面提到的一些方法吧

import java.util.*;
import java.util.List;

public class HelloWorld {
    public static void main(String[] args) throws Exception {
        // List<int> s  = new ArrayList<>();  // java: 意外的类型 需要: 引用 找到:    int
        List<String> s = new ArrayList<>();
        System.out.println(s.isEmpty());  // true判断是否为空
        s.add("a");  // 添加
        // s.add(1);  //   java: 不兼容的类型: int无法转换为jåava.lang.String, 因为已经指定类型,所以只能传入指定类型的
        s.add("b");
        System.out.println(s.add("c"));  // true
        System.out.println(s.size());  // 3
        System.out.println(s);  // [a, b, c]
        System.out.println(s.contains("a"));  // true 包含关系
        List<String> s1 = List.of("d", "e");  // 这个返回的只是一个只读的List,因为List只是一个接口
        // s1.add("m"); // java.lang.UnsupportedOperationException
        List<String> s2 = List.of("f", "g");
        s.addAll(s1);
        System.out.println(s);  // [a, b, c, d, e] 插入一个对象
        s.addAll(3, s2);
        System.out.println(s);  // [a, b, c, f, g, d, e]  在指定位置插入
        s.remove("f");
        System.out.println(s);  // [a, b, c, g, d, e]  删除
        System.out.println(s.get(1));  // b  获取指定下表的元素
        // String[] m = s.toArray();  // java: 不兼容的类型: java.lang.Object[]无法转换为java.lang.String[],这个是因为不支持的,随意这个运行之前就是object
        String[] m1 = new String[3];
        String[] m2 = new String[9];
        String[] m3 = s.toArray(m1);  // 可以这样转化,List会把值赋值给传入对象,但是如果数字不够长,List会为他生成新的对象
        String[] m4 = s.toArray(m2);  // 可以这样转化,
        for (String i : m1) {
            System.out.println(i);
        }  // null null null 数组不够长,我们应该清楚,数组扩容之后,会生成一个新对象,愿对象就会被清空
        for (String i : m3) {
            System.out.println(i);
        }  // a b c g d e 这个就是被扩容之后的新对象,所以要记得写返回值
        for (String i : m2) {
            System.out.println(i);
        }  // a b c g d e null null null  这个数组定义的够长,所有值是传进去了
        for (String i : m4) {
            System.out.println(i);
        } // a b c g d e null null null
        // 一般情况下,我们肯定希望正好,可以结合上size或者直接为0
        String[] m5 = s.toArray(new String[0]);
        String[] m6 = s.toArray(new String[s.size()]);
        for (String i : m5) {
            System.out.println(i);
        } // a b c g d e 正好
        for (String i : m6) {
            System.out.println(i);
        } // a b c g d e 正好
        // List 的循环,for each的方法帮助我们封装了迭代,原始应该是这样的
        for (Iterator<String> ss = s.iterator(); ss.hasNext(); ) {
            String sss = ss.next();
            System.out.println(sss);
        } // a b c g d e
        // 如上面所说,for帮助我们做了封装,所以可以直接这样写
        for (String ss : s) {
            System.out.println(ss);
        } // a b c g d e
    }
}

说完了List,接下来我们来看一下map,map是key-value的一种数据结构,他的方法类是HashMap,源码感觉差不太多,都是一些接口定义了一些方法,我们直接看使用,map的实现方法是它使用一个比较大的数组,来存储所有的value,然后计算key的值(hascode),然后根据这个作为索引,将value存储在指定位置,因此如果想用使用自己的类来dingyikey,必须实现equalshenhascode这两个方法,因为这个不常用,就不再展示,但我们既然知道这个原理,就能想象的到map是无序的。接下来看一下map的常用操作

import java.util.*;

public class HelloWorld {
    public static void main(String[] args) throws Exception {
        Map<String, Integer> s = new HashMap<>();
        s.put("a", 1);  // 添加
        s.put("b", 2);
        s.put("c", 3);
        System.out.println(s.put("d", 4)); // null
        System.out.println(s.put("d", 4)); // 4  如果重复,就会把原来的值替换,并抛出原来的值
        System.out.println(s.get("a"));  // 1 获取
        System.out.println(s.containsKey("f"));  // false
        System.out.println(s.getOrDefault("f", 1));  // 1 如果获取失败,就会给出默认值
        System.out.println(s.remove("f"));  // null  删除
        System.out.println(s.remove("a"));  // 1  如果有删除,就会返回值
        // 循环所有的key
        for (String key : s.keySet()) {
            System.out.println(key);
            System.out.println(s.get(key));
        }
        // 循环所有的key-value
        for (Map.Entry<String, Integer> ss : s.entrySet()) {
            System.out.println(ss);
            System.out.println(ss.getKey() + ss.getValue());
        }
    }
}

另外还有一种实现map的方法是枚举map,如果对于一些比较少的,可以直接使用这个类型,它并非使用key的code进行安排缩阴的,而是直接使用key,因此效率会更高

import java.time.DayOfWeek;
import java.util.*;

public class HelloWorld {
    public static void main(String[] args) throws Exception {
        Map<DayOfWeek, String> map = new EnumMap<>(DayOfWeek.class);
        map.put(DayOfWeek.MONDAY, "星期一");
        map.put(DayOfWeek.WEDNESDAY, "星期二");
        map.put(DayOfWeek.FRIDAY, "星期五");
        System.out.println(map.get(DayOfWeek.FRIDAY));  // 星期五
        System.out.println(map);  // {MONDAY=星期一, WEDNESDAY=星期二, FRIDAY=星期五}
    }
}

既然上面提到的map是无序的,就如同python中dict是无序的,但还是有有序字典OrderDict,因此java也肯定有有序map,他实现的接口是SortMap, 实现类是TreeMap,但是如果要使用自己的定义的类作为key,请记得要实现compare方法

import java.util.Comparator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

public class HelloWorld {
    public static void main(String[] args) throws Exception {
        SortedMap<String, Integer> s = new TreeMap<>(); // 初始化一个有序map
        s.put("a", 1);  // 添加
        s.put("b", 2);
        s.put("c", 3);
        System.out.println(s);  // {a=1, b=2, c=3}
        // 循环打印
        for (Map.Entry<String, Integer> ss : s.entrySet()) {
            System.out.println(ss);
        }  // a=1 b=2 c=3
        // 初始化一个带我们自定义排序方法的有序map,查看结构跟上面相反
        SortedMap<String, Integer> s1 = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return -o1.compareTo(o2);
            }
        });
        s1.put("a", 1);
        s1.put("b", 2);
        s1.put("c", 3);
        System.out.println(s1);  // {c=3, b=2, a=1}
        for (Map.Entry<String, Integer> ss : s1.entrySet()) {
            System.out.println(ss);
        }  // c=3 b=2 a=1
    }
}

然后我们再来看一下set,集合,他最出名的不就是去重,他有两个实现类,一个是HashSet无序,另外一个是TreeSet有序,而有序集合里面的元素如果没有实现compaer接口,需要初始化时传入一个自定义的比较,跟有序集合类似,就不再赘述

import java.util.*;

public class HelloWorld {
    public static void main(String[] args) throws Exception {
        // 无序集合
        Set<String> s = new HashSet<>();
        s.add("c");
        s.add("b");  // 添加
        s.add("a");
        System.out.println(s);  // [a, b, c]
        System.out.println(s.contains("a"));  // true  包含
        System.out.println(s.remove("d"));  // false  删除,没有删除,返回false
        System.out.println(s.remove("a"));  // true
        System.out.println(s);  // [b, c]
        for (String ss : s) {
            System.out.println(ss);
        }  // b c
        // 有序集合
        Set<String> s1 = new TreeSet<>();
        s.add("a");
        s.add("b");
        s.add("c");
        System.out.println(s);  // [a, b, c]
        for (String ss : s) {
            System.out.println(ss);
        }  // a b c
    }
}

接下来看一下队列,队列分为几种,一个是FIFO--Queue,另外一个是有优先级的 PriorityQueue,而这个是必须实现compaer接口,否则没办法选择优先级, 还有双端队列 -- Deque

我们来看一下实例

import java.util.*;

public class HelloWorld {
    public static void main(String[] args) throws Exception {
        // FIFO队尾进,队首出
        Queue<String> q1 = new LinkedList<>();  // 这个 LinkedList 也实现了List接口,根据需要选择,这个就是链表,但是作为List来用,没有特许需求的话,有点吗,他是按照链表来存储的
        // 两端均可进可出
        Deque<String> q2 = new LinkedList<>();
        // 根据默认的或自定义对比方法,出队列,String有compaer方法,我只是自定义了一个反序的
        Queue<String> q3 = new PriorityQueue<>(new Comparator<String>() {
            public int compare(String a, String b) {
                return -a.compareTo(b);
            }
        });
        // add 添加方法,如果添加失败就报错,比如队列满了
        // FIFO添加对象方法
        q1.add("a");
        q1.add("b");
        q1.add("c");
        System.out.println(q1);  // [a, b, c]
        for (String qq : q1) {
            System.out.println(qq);
        }  // a b c
        // 双端队列添加方法
        q2.addFirst("a");
        q2.addFirst("b");
        q2.addLast("d");
        q2.addLast("c");
        System.out.println(q2);  // [b, a, d, c]
        for (String qq : q2) {
            System.out.println(qq);
        }  // b a d c
        // 优先级队列添加方法
        q3.add("a");
        q3.add("b");
        q3.add("c");
        System.out.println(q3);  // [c, a, b]
        for (String qq : q3) {
            System.out.println(qq);
        }  // c a b
        // offer 添加方法,会返回boolean值,告知是否添加成功,不会报错
        q1.offer("a");
        q1.offer("b");
        System.out.println(q1.offer("c"));  // true
        System.out.println(q1);  // [a, b, c, a, b, c]
        for (String qq : q1) {
            System.out.println(qq);
        }  // a b c
        // 双端队列添加方法
        q2.offerFirst("a");
        q2.offerFirst("b");
        q2.offerLast("d");
        q2.offerLast("c");
        System.out.println(q2);  // [b, a, b, a, d, c, d, c]
        for (String qq : q2) {
            System.out.println(qq);
        }  // b a b a d c d c
        // 优先级队列添加方法
        q3.offer("a");
        q3.offer("b");
        q3.offer("c");
        System.out.println(q3);  // [c, b, c, a, a, b]
        for (String qq : q3) {
            System.out.println(qq);
        }  // c b c a a b
        // 获取首元素并删除
        // 删除失败会报错
        Queue<Integer> i = new LinkedList<>();
        // i.remove();  // java.util.NoSuchElementException
        q1.remove();
        System.out.println(q1);  // [b, c, a, b, c]
        q2.removeFirst();
        System.out.println(q2);  // [a, b, a, d, c, d, c]
        q2.removeLast();
        System.out.println(q2);  // [a, b, a, d, c, d]
        q3.remove();
        System.out.println(q3);  // [c, b, b, a, a]
        // 删除失败不会报错,会返回false 或者 null
        System.out.println(i.poll());
        System.out.println(q1.poll());  // b
        System.out.println(q1);  // [c, a, b, c]
        q2.pollFirst();
        System.out.println(q2);  // [b, a, d, c, d]
        q2.pollLast();
        System.out.println(q2);  // [b, a, d, c]
        q3.poll();
        System.out.println(q3);  // [b, a, b, a]
        // 取首元素但是不会删除
        // 删除失败会报错
        System.out.println("----");
        // i.element();  // java.util.NoSuchElementException
        System.out.println(q1.element());  // c
        System.out.println(q1);  // [c, a, b, c]
        q1.element();
        System.out.println(q1);  // [c, a, b, c]
        q2.getFirst();
        System.out.println(q2);  // [b, a, d, c]
        System.out.println(q2.getFirst());  // b
        System.out.println(q2);  // [b, a, d, c]
        System.out.println(q2.getLast());  // c
        System.out.println(q2);  // [b, a, d, c]
        q2.getLast();
        System.out.println(q2);  // [b, a, d, c]
        q3.element();
        System.out.println(q3);  // [b, a, b, a]
        q3.element();
        System.out.println(q3);  // [b, a, b, a]
        // 删除失败不会报错,会返回false 或者 null
        System.out.println(i.peek());  // null
        System.out.println(q1.peek());  // c
        System.out.println(q1);  // [c, a, b, c]
        System.out.println(q1.peek());  // c
        System.out.println(q1);  // [c, a, b, c]
        System.out.println(q2.peekFirst());  // b
        System.out.println(q2);  // [b, a, d, c]
        q2.peekFirst();
        System.out.println(q2);  // [b, a, d, c]
        System.out.println(q2.peekLast());  // c
        System.out.println(q2);  // [b, a, d, c]
        q2.peekLast();
        System.out.println(q2);  // [b, a, d, c]
        q3.peek();
        System.out.println(q3);  // [b, a, b, a]
        q3.peek();
        System.out.println(q3);  // [b, a, b, a]

        // 双端队列还有 pop 的 取出队首且删除的犯法,但取不到就会报错
        System.out.println(q2.pop());  // b
        System.out.println(q2.pop());  // a
        System.out.println(q2.pop());  // d
        System.out.println(q2.pop());  // c
        //System.out.println(q2.pop());  // java.util.NoSuchElementException
        // 还有push增加方法
        q2.push("a");
        q2.push("b");
        System.out.println(q2);
        // 因此我们可以使用Deque来模拟栈
        Deque<String> q4 = new LinkedList<>();
        // 模拟压栈
        q4.push("a");
        q4.push("b");
        // 模拟出栈
        System.out.println(q4); // [b, a]
        System.out.println(q4.pop());  // b 删除队首,并跑操
        System.out.println(q4);  // [a]
        System.out.println(q4.peek()); // a 只取队首的值,不删除
        System.out.println(q4); // [a]
    }
}

我们确实是可以使用Deque来模拟栈的

原文地址:https://www.cnblogs.com/yangshixiong/p/12172253.html

时间: 2024-11-06 09:59:43

java入门篇11 --- 集合的相关文章

《Java从入门到放弃》JavaSE入门篇:集合

今天来讲讲Java中的集合和常见集合类型的使用. 什么是集合呢? 刚好最近学校里面军训,只听到教官一声喊:"集合!!!"各位小萌新们就屁颠屁颠的跑过来排列整齐了,这就是集合··· Java中的集合也是一样的意思,Java一声喊:"集合!!!",那么我们就把需要放在一起的数据放到一个集合中.有的人会说"数组不就有这个功能么".是的,数组是有这个功能,但集合与数组相比,功能会更多些,而且不同的集合侧重点不一样,具体有哪些优势,我们接下来讲解. 集合与

Java学习日记-11 集合(1)

Collection接口集合中存储的只是对象的引用,不是对象本身. 1.ArrayList<E>类1.1ArrayList和Collection的关系 public interface List<E>extends Collection<E> public class ArrayList<E> implements List<E> 1.2构造方法 ArrayList() 构造一个初始容量为 10 的空列表. ArrayList(Collectio

Java入门系列之集合LinkedList入门(八)

前言 前面两节内容我们详细介绍了ArrayList,一是手写实现ArrayList数据结构,而是通过分析ArrayList源码看看内置实现,关于集合内容一如既往,本节课我们继续学习集合LinkedList,我们首先入门LinkedList数据结构,然后再去看看LinkedList源码是如何实现的,我们开始吧. LinkedList入门 LinkedList内置是通过双链表数据结构来存储数据,和ArrayList不同的是,ArrayList属于真正意义物理意义上的线性结构,而LinkedList也

Java 基础篇之集合

List 集合 List 集合中元素有序.可重复,集合中每个元素都有其对应的索引顺序. List 判断两个对象相等,只要通过 equals 方法比较返回 true 即可. 看个例子: public class A { public boolean equals(Object obj) { return true; } } import java.util.ArrayList; import java.util.List; public class ListTest2 { public stati

Java入门系列之集合Hashtable源码分析(十一)

前言 上一节我们实现了散列算法并对冲突解决我们使用了开放地址法和链地址法两种方式,本节我们来详细分析源码,看看源码中对于冲突是使用的哪一种方式以及对比我们所实现的,有哪些可以进行改造的地方. Hashtable源码分析 我们通过在控制台中实例化Hashtable并添加键值对实例代码来分析背后究竟做了哪些操作,如下: public static void main(String[] args) { Hashtable hashtable = new Hashtable(); hashtable.p

Java入门系列之集合HashMap源码分析(十四)

前言 我们知道在Java 8中对于HashMap引入了红黑树从而提高操作性能,由于在上一节我们已经通过图解方式分析了红黑树原理,所以在接下来我们将更多精力投入到解析原理而不是算法本身,HashMap在Java中是使用比较频繁的键值对数据类型,所以我们非常有必要详细去分析背后的具体实现原理,无论是C#还是Java原理解析,从不打算一行行代码解释,我认为最重要的是设计思路,重要的地方可能会多啰嗦两句. HashMap原理分析 我们由浅入深,循序渐进,首先了解下在HashMap中定义的几个属性,稍后会

java入门篇3 --- 基本数据类型的运算

一.整数 1.运算 java的整数运算遵从基本的四则运算,不再赘述 下面说一下整数的除法得到的结果永远是精确的,也就是除不尽就给你取整,我记得python2的int类型会保留小数,python3之后也只保留整数 另外取余也是使用%,除法如果除数是0,运行时会报错. 注意,整数有范围,如果超出最大的会溢出,感觉像是又重新走了一个循环.请根据需要使用整型的类型,如果数值大于int范围,可以使用long 另外java也支持n++, n+=1语法糖 public class HelloWorld { p

Java初级篇 1-1 Java特点以及版本

1.跨平台是Java语言的核心优势.在各个平台上都可以使用Java这门语言. 在企业 安卓 大数据 云计算等等行业的主流语言. 2.JavaSE(Java Standard Edition):标准版,定位在个人计算机上的应用.也就是桌面上的应用(这也是Java的一个短板). 3.JavaEE(Java Enterprise Edition):企业版,定位在服务器端的应用.例如银行取钱 服务员就是利用服务器端进行操作. 4.JavaME(Java Micro Edition):微型版,定位在消费性

java入门篇4 --- 引用类型

1.String字符串 我们常用的字符串属于引用类型,它可以包含0至n个字符,String使用双引号,字符串的拼接也可以使用+ public class HelloWorld { public static void main(String[] args) { String s = "我爱中国"; String s1 = "i " + "love " + "china"; String s2 = null; // String