java 集合学习笔记

Collection接口

API

Modifier and TypeMethod and Description
booleanadd(E e) 确保此集合包含指定的元素(可选操作)。
booleanaddAll(Collection<? extends E> c) 将指定集合中的所有元素添加到此集合(可选操作)。
voidclear() 从此集合中删除所有元素(可选操作)。
booleancontains(Object o) 如果此集合包含指定的元素,则返回 true
booleancontainsAll(Collection<?> c) 如果此集合包含指定 集合中的所有元素,则返回true。
booleanequals(Object o) 将指定的对象与此集合进行比较以获得相等性。
inthashCode() 返回此集合的哈希码值。
booleanisEmpty() 如果此集合不包含元素,则返回 true
Iterator<E>iterator() 返回此集合中的元素的迭代器。
default Stream<E>parallelStream() 返回可能并行的 Stream与此集合作为其来源。
booleanremove(Object o) 从该集合中删除指定元素的单个实例(如果存在)(可选操作)。
booleanremoveAll(Collection<?> c) 删除指定集合中包含的所有此集合的元素(可选操作)。
default booleanremoveIf(Predicate<? super E> filter) 删除满足给定谓词的此集合的所有元素。
booleanretainAll(Collection<?> c) 仅保留此集合中包含在指定集合中的元素(可选操作)。
intsize() 返回此集合中的元素数。
default Spliterator<E>spliterator() 创建一个Spliterator在这个集合中的元素。
default Stream<E>stream() 返回以此集合作为源的顺序 Stream
Object[]toArray() 返回一个包含此集合中所有元素的数组。
<T> T[]toArray(T[] a) 返回包含此集合中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。

一、List

元素有序、可重复的集合;“动态数组”

添加元素所在的类要重写equals方法

一、ArrayList

简单源码分析:

源码方法作用或实现
ArrayList list = new ArrayList();在底层创建长度位10的Object数组elementData;在JDK8中,使用无参构造器是,不会创建长度为10的数组,而是{};在第一次调用add()时,会自动创建长度为10的数组;后面的操作与之前一致;延迟数组创建,可节省内存
list.add(“aaa”);elementData[0] = “aaa”;当elementData的长度不够时,会扩容数组为原来的1.5倍,并将原来的数据copy到扩容后的数组
ArrayList list = new ArrayList(5);有参构造器;传入参数后会创建一个该大小的数组;在已知大小的情况下建议使用该构造器。

常用方法:(除去Collection接口中的方法)

返回值方法描述
voidadd(int index, E element)`在此列表中的指定位置插入指定的元素。
voidaddAll(int index, Collection<? extends E> c)将指定集合中的所有元素插入到此列表中,从指定的位置开始。
Eget(int index)返回此列表中指定位置的元素。
intindexOf(Object o)返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
intlastIndexOf(Object o)返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
ListIteratorlistIterator(int index)从列表中的指定位置开始,返回列表中的元素(按正确顺序)的列表迭代器。
Eremove(int index)删除该列表中指定位置的元素。
Eset(int index, E element)用指定的元素替换此列表中指定位置的元素。
ListsubList(int fromIndex, int toIndex)返回此列表中指定的 fromIndex (包括)和 toIndex之间的独占视图。

排序:

List list = Arrays.asList(2,5,94,3,5,4,7,5,4,321,5);

list.sort(Comparator.naturalOrder());   //从小到大

list.sort(Comparator.reverseOrder());    //从大到小

List遍历:**

	    List<Integer> list = Arrays.asList(2,5,94,3,5,4,7,5,4,321,5);

        //方式一:普通循环
        for (int i=0; i<list.size(); i++){
            System.out.println(list.get(i));
        }

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

        //方式二:增强for循环
        for (int i : list) {
            System.out.println(i);
        }

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

        //方式三:迭代器
        Iterator<Integer> iterator = list.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

二、LinkedList

简单源码分析:

源码方法作用或实现
transient int size = 0; transient Node first; transient Node last;创建一个LinkedList时,会指明链表的长度、第一个节点(临时)和最后一个节点(临时)
private static class Node {…}节点的内部类,用于声明一个节点;包括由上一个节点、数据、下一个节点

添加元素(add()会方法调用该方法)

    void linkLast(E e) {
        final Node<E> l = last;    //获取最后一个节点
        final Node<E> newNode = new Node<>(l, e, null);     //构建一个新的节点,l为prev,next为空
        last = newNode;          //将新的节点作为最后一个节点
        if (l == null)           //如果最后一个节点是null,则将新的节点作为第一个节点
            first = newNode;
        else                      //否则,最后一个节点的next指向新的节点
            l.next = newNode;
        size++;
        modCount++;
    }

常用方法:(LinkedList特有的方法)

返回值方法描述
voidaddLast(E e)将指定的元素追加到此列表的末尾。
voidaddFirst(E e)`在该列表开头插入指定的元素。
EgetFirst()返回此列表中的第一个元素。
EgetLast()返回此列表中的最后一个元素。

LinkedList可以充当对或栈,所以具有一些符合栈和队列特性的方法

booleanoffer(E e) 将指定的元素添加为此列表的尾部(最后一个元素)。
booleanofferFirst(E e) 在此列表的前面插入指定的元素。
booleanofferLast(E e) 在该列表的末尾插入指定的元素。
Epeek() 检索但不删除此列表的头(第一个元素)。
EpeekFirst() 检索但不删除此列表的第一个元素,如果此列表为空,则返回 null
EpeekLast() 检索但不删除此列表的最后一个元素,如果此列表为空,则返回 null
Epoll() 检索并删除此列表的头(第一个元素)。
EpollFirst() 检索并删除此列表的第一个元素,如果此列表为空,则返回 null
EpollLast() 检索并删除此列表的最后一个元素,如果此列表为空,则返回 null
Epop() 从此列表表示的堆栈中弹出一个元素。
voidpush(E e) 将元素推送到由此列表表示的堆栈上。

三、Vector

较少使用。创建时会直接创建长度为10的数组(jdk7、8都是),扩容会变为原来的两倍

四、ArrayList、LinkedList、Vector的异同

  • 同:三者都是实现了List接口;存储结构都是有序的、可重复的
  • 不同:
    1. Vector效率低(线程安全);其他的效率高(线程不安全)
    2. LinkedList适用于增加和删除(底层由双向链表实现);ArrayList由Object[ ]实现,适合数据的添加和查找;Vector底层由Object[] elementData实现


二、Set:

元素无序、不可重复的集合;set接口中没有新定义方法

在使用SET时,要重写所添加对象所在类的equals和hashCode方法;尽可能保证两个方法的一致,即如果equals的结果为false,则二者的hashcode也应该不一样

一、HashSet

*无序:不等于随机;底层使用数组实现,但是不根据数组的索引添加,而是根据数据的hashcode方法获得的值来添加

*不可重复性:保证添加的元素按照equals比较时,不能返回true;即equals比较结果必须为不相同

添加元素过程理解:1.首先调用待添加对象所在类的hashcode方法计算hash值;2.根据hash值使用算法计算出该值在hashset底层数组中的具体位置;3.如果在数组中的该位置没有元素,则直接将该值添加至数组中,即完成添加;4.如果数组的该位置已有元素,则比较其hash值,如果不同,在该位置使用链表存储这些元素;5.如果hash值也行同,则调用待添加对象所在类中的equals方法,如果返回true,则该值重复,不在添加,如果返回false,则在该位置的链表中添加该值

API:同Collection接口中的方法

Set遍历:

Set set = new HashSet();
        set.add(1);
        set.add("aaa");
        set.add(false);
        set.add(55);

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

		System.out.println("--------------------");
		//方法二
        for (Object o: set) {
            System.out.println(o);
        }

二、LinkedHashSet

LinkedHashSet存储的方式与HashSet一样;但是遍历结果与添加的顺序相通,原因为:在添加数据的同时,其维护了添加数据的先后顺序,具体实现为每个元素都具有头和尾,分别指向前一个元素和后一个元素

优点:频繁的遍历效率高于HashSet

三、TreeSet

TreeSet中的存储结构为红黑树

Set中添加的数据必须是同一个类的数据

可以按照的对象的指定属性排序

注:TreeSet中的比较对象是否相同不适用equals,而使用compareTo( )/Compare()的返回值是否为0,0表示相同;

使用Comparable接口规定排序的规则(自然排序):

//对象类persion,其他方法已省略,只关注compareTo方法的重写
public class persion implements Comparable{
    private String name;
    private int age;

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

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

    @Override
    public int compareTo(Object o) {
        if(o instanceof persion){
            persion p = (persion)o;
            if(this.age != p.age){
                return Integer.compare(this.age,p.age);
            }else{
                return this.name.compareTo(p.name);
            }
        }else{
            throw new RuntimeException("传入参数错误");
        }
    }
}

//实现
 public static void main(String[] args) {
        Set set = new TreeSet();
        set.add(new persion("zhangsan",15));
        set.add(new persion("lisi",20));
        set.add(new persion("wangwu",65));
        set.add(new persion("liuiz",53));

        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
/*输出:
persion{name='zhangsan', age=15}
persion{name='lisi', age=20}
persion{name='liuiz', age=53}
persion{name='wangwu', age=65}

*/

使用Comparator实现定制排序:

    public static void main(String[] args) {
        Comparator com = new Comparator(){

            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof persion && o2 instanceof persion){
                    persion p1 = (persion)o1;
                    persion p2 = (persion)o2;
                    return Integer.compare(p1.getAge(),p2.getAge());
                }else{
                    throw new RuntimeException("出入参数错误");
                }
            }
        };

        Set set = new TreeSet(com);
        set.add(new persion("zhangsan",15));
        set.add(new persion("lisi",20));
        set.add(new persion("wangwu",65));
        set.add(new persion("liuiz",53));


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

四、HashSet、LinkedHashSet、TreeSet异同

  1. HashSet:为set的主要实现类;线程不安全;可存放null值
  2. LinkedHashSet:为HashSet的子类;遍历时可以按照添加数据时的顺序来遍历;频繁的遍历效率高于HashSet
  3. TreeSet:可以按照的对象的指定属性排序

Map接口

key–value

一、HashMap

hashMap结构理解

  • key:无序的、不可重复的;可以理解为set存储 >>>key所在的类要重写equals()和hashCode()方法
  • value:无序的、可重复的;可以理解为Collection存储 >>>value所在的类要重写equals方法
  • enrty:key-value构成entry对象;entry无序的、不可重复的;可以理解为使用set存储

在这里插入图片描述

底层实现:

(jdk7=数组+链表;jdk8=数组+链表+红黑树)

jdk7:

源码描述
Map map = new HashMap();底层创建长度为16的数组;类型为Entry [ ] table
map.put(k1,v1);1.根据key所在类的hashCode方法,计算hash值,通过计算获得其在数组中的存放位置;2.如果该位置为空,则将该k-v放入该位置;3.如果该位置已有数据,则比较他们的hash值,如果不同,则添加该k-v;如果相同,则调用待添加k所在类的equals方法:如果返回false,则添加成功;如果返回true,使用v替换该位置的原来的value(覆盖)。(如果原位置已有元素,则以链表的形式添加新的元素;涉及扩容时:扩容为原来的两倍【超出临界值且该位置已有元素才会扩容】,并复制原来的数据)

jdk8:

  1. new HashMap();底层没有创建长度为16的数组
  2. 底层使用的数组为Node[ ];
  3. 首次调用put()方法时会创建长度为16的数组;
  4. 当数组的某一个索引位置的元素数量>8 ,且当数组长度超过64时,此索引位置上的元素改用红黑树存储

常用API:

返回值方法描述
voidclear()从这张地图中删除所有的映射。
booleancontainsKey(Object key)如果此映射包含指定键的映射,则返回true。
booleancontainsValue(Object value)如果此地图将一个或多个键映射到指定值,则返回 true 。
Vget(Object key)返回到指定键所映射的值,或 null如果此映射包含该键的映射。
booleanisEmpty()如果此地图不包含键值映射,则返回 true。
Vput(K key, V value)将指定的值与此映射中的指定键相关联。
voidputAll(Map<? extends K,? extends V> m)将指定地图的所有映射复制到此地图。
Vremove(Object key)从该地图中删除指定键的映射(如果存在)。
booleanremove(Object key, Object value)仅当指定的密钥当前映射到指定的值时删除该条目。
Vreplace(K key, V value)只有当目标映射到某个值时,才能替换指定键的条目。
booleanreplace(K key, V oldValue, V newValue)仅当当前映射到指定的值时,才能替换指定键的条目
intsize()返回此地图中键值映射的数量。
Collectionvalues()返回此地图中包含的值的Collection视图。
Set<Map.Entry<K,V>>entrySet()返回此地图中包含的映射的Set视图。
SetkeySet()返回此地图中包含的键的Set视图。

hashMap的遍历:

public static void main(String[] args) {
        Map<String,Integer> map = new LinkedHashMap();
        map.put("a",1);
        map.put("b",3);
        map.put("c",3);

        //遍历map中的key
        Set<String> keySet = map.keySet();
        Iterator<String> iterator = keySet.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

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

        //遍历map中的value
        Collection<Integer> values = map.values();
        Iterator<Integer> iterator1 = values.iterator();
        while(iterator1.hasNext()){
            System.out.println(iterator1.next());
        }

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

        //遍历map:方法一
        for (Map.Entry<String,Integer> e: map.entrySet()) {
            System.out.print(e.getKey());
            System.out.print("   ");
            System.out.print(e.getValue());
            System.out.println();
        }

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

        //遍历map:方法二
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        Iterator<Map.Entry<String, Integer>> iterator2 = entries.iterator();
        while(iterator2.hasNext()){
            Map.Entry e = (Map.Entry)iterator2.next();
            System.out.print(e.getKey());
            System.out.print("   ");
            System.out.print(e.getValue());
            System.out.println();
        }

    }

/*输出:
a
b
c
-----------------
1
3
3
-----------------
a   1
b   3
c   3
-----------------
a   1
b   3
c   3
*/

二、LinkedHashMap

是HashMap的子类,方法都一样,知识多了两个before、after指针,当频繁使用遍历时效率更高

三、TreeMap

*添加的数据类型必须都是同一类型的

自然排序实现(类实现Comparable接口):

//传入的参数类,关注接口的实现与方法的重写
public class student implements Comparable{    //实现Comparable接口
    private String name;
    private int age;

    @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);
    }

    public student() {
    }

    public student(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 int compareTo(Object o) {    //重写compareTo方法,将根据重写的逻辑来排序
        if(o instanceof student){
            student s = (student)o;
            return this.name.compareTo(s.name);
        }else{
            throw new RuntimeException("参数错误");
        }
    }
}
//遍历TreeMap查看排序
public static void main(String[] args) {
        TreeMap<student,Integer> map = new TreeMap();
        student s1 = new student("shangsan", 10);
        student s2 = new student("lisi", 15);
        student s3 = new student("wangwu", 11);
        student s4 = new student("liu", 120);

        map.put(s1,1);
        map.put(s2,2);
        map.put(s3,3);
        map.put(s4,4);

        for (Map.Entry<student,Integer> e :map.entrySet()) {
            System.out.print(e.getKey().getName());
            System.out.print("  ");
            System.out.print(e.getValue());
            System.out.println();
        }
    }
/*输出:
lisi  2
liu  4
shangsan  1
wangwu  3
*/

定制排序(new TreeSet()时传入Comparator):

public static void main(String[] args) {
        Comparator<student2> com = new Comparator(){    //创建Comparator对象,并重写compare方法

            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof student2){
                    student2 s1 = (student2)o1;
                    student2 s2 = (student2)o2;
                    return Integer.compare(s1.getAge(),s2.getAge());
                }else{
                    throw new RuntimeException("参数错误");
                }
            }
        };

        TreeMap<student2,Integer> map = new TreeMap(com);    //将创建的Comparator对象传入TreeMap构造器,将根据此规则排序
        student2 s1 = new student2("shangsan", 10);
        student2 s2 = new student2("lisi", 15);
        student2 s3 = new student2("wangwu", 11);
        student2 s4 = new student2("liu", 120);

        map.put(s1,1);
        map.put(s2,2);
        map.put(s3,3);
        map.put(s4,4);

        for (Map.Entry<student2,Integer> e :map.entrySet()) {
            System.out.print(e.getKey().getName());
            System.out.print("  ");
            System.out.print(e.getValue());
            System.out.println();
        }
    }
/*输出:
shangsan  1
wangwu  3
lisi  2
liu  4
*/

五、Hashtable:

Properties:作为Hashtable的子类(是一种map)

多用于配置文件

###配置文件jdbc.properties信息
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mytest?serverTimezone=UTC&useSSL=false
jdbc.username=root
jdbc.password=root
//加载配置文件
public static void main(String[] args) {
        Properties properties = new Properties();
        try {
            FileInputStream fis = new FileInputStream("jdbc.properties");
            properties.load(fis);
            String driver = properties.getProperty("jdbc.driver");
            String url = properties.getProperty("jdbc.url");
            String username = properties.getProperty("jdbc.username");
            String password = properties.getProperty("jdbc.password");
            System.out.println(driver + "  " + url + "   "+ username +"   "+ password);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
/*输出:
com.mysql.cj.jdbc.Driver  jdbc:mysql://localhost:3306/mytest?serverTimezone=UTC&useSSL=false   root   root
*/

区别:

  • HashMap:Map接口的主要实现类;线程不安全,效率高;可以存储null的key或value
  • LinkedHashMap:作为HashMap的子类;保证在遍历map元素时实现按照添加时的顺序(添加有两个指针指向前一个和后一个元素);频繁遍历效率高
  • TreeMap:添加的key-value可以按照key来实现自然排序或定制排序
  • Hashtable:线程安全,效率低;不可以存储null的key或value
  • Properties:作为Hashtable的子类;常用来作为配置文件。key和value都是String

Collections工具类

Collections用于操作set、list、map的工具类

常用方法:

  • reverse(List<?> list) 反转指定列表中元素的顺序。

    	    List<String> list1 = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
            Collections.reverse(list1);
            for (String s:list1) {
                System.out.println(s);
            }
    /*输出:
    eee
    ddd
    ccc
    bbb
    aaa
    */
    
  • shuffle(List<?> list)

    	    List<String> list1 = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
            Collections.shuffle(list1);
            for (String s: list1) {
                System.out.println(s);
            }
    /*输出:  随机序列
    bbb
    ddd
    ccc
    eee
    aaa
    */
    
  • sort(List list) 根据其元素的natural ordering对指定的列表进行排序(简易理解为:从小到大)

  • sort(List list, Comparator<? super T> c) 根据指定的比较器引起的顺序对指定的列表进行排序。

    		List<String> list1 = Arrays.asList("aaa", "ccc", "ddd", "bbb","eee");
            Collections.sort(list1, Comparator.reverseOrder());    //倒叙
            for (String s: list1) {
                System.out.println(s);
            }
            System.out.println("--------------");
            Collections.sort(list1, Comparator.naturalOrder());    //自然排序
            for (String s: list1) {
                System.out.println(s);
            }
    
  • swap(List<?> list, int i, int j) 交换指定列表中指定位置的元素。

    	    List<String> list1 = Arrays.asList("aaa", "ccc", "ddd", "bbb","eee");  
            Collections.swap(list1,0,4);    //交换索引为0和4的元素的位置
            for (String s: list1) {
                System.out.println(s);
            }
    /*输出:
    eee
    ccc
    ddd
    bbb
    aaa
    */
    
    
  • max(Collection<? extends T> coll) 根据其元素的 自然顺序返回给定集合的最大元素。

    	    List<String> list1 = Arrays.asList("ccc", "ddd", "bbb","eee","aaa");
            String max = Collections.max(list1);
            System.out.println(max);    //eee
    
            HashSet<Integer> set = new HashSet<>();
            set.add(5);
            set.add(8);
            set.add(4);
            Integer max1 = Collections.max(set);
            System.out.println(max1);   //8
    
  • max(Collection<? extends T> coll, Comparator<? super T> comp) 根据指定的比较器引发的顺序返回给定集合的最大元素。

    List<String> list1 = Arrays.asList("ccc", "ddd", "bbb","eee","aaa");
            String max = Collections.max(list1,new Comparator(){
    
                @Override
                public int compare(Object o1, Object o2) {
                    if(o1 instanceof String && o2 instanceof String){
                        String s1 = (String)o1;
                        String s2 = (String)o2;
                        return - s1.compareTo(s2);
                    }else{
                        throw new RuntimeException("参数错误");
                    }
                }
            });
            System.out.println(max);    //eee
    
            HashSet<Integer> set = new HashSet<>();
            set.add(5);
            set.add(8);
            set.add(4);
            Integer max1 = Collections.max(set,Comparator.reverseOrder());
            System.out.println(max1);   //8
    
  • min(Collection<? extends T> coll) 根据其元素的 自然顺序返回给定集合的最小元素。

  • min(Collection<? extends T> coll, Comparator<? super T> comp) 根据指定的比较器引发的顺序返回给定集合的最小元素。

  • frequency(Collection<?> c, Object o) 返回指定集合中与指定对象相等的元素数。

            List<String> list1 = Arrays.asList("ccc", "ddd", "bbb", "ddd","eee","aaa", "ddd");
            int ddd = Collections.frequency(list1, "ddd");
            System.out.println(ddd);    //3
    
  • replaceAll(List list, T oldVal, T newVal) 将列表中一个指定值的所有出现替换为另一个。

            List<String> list1 = Arrays.asList("ccc", "ddd", "bbb", "ddd","eee","aaa", "ddd");
            Collections.replaceAll(list1,"ddd","replace");
            for (String s: list1) {
                System.out.println(s);
            }
    /*输出:
    ccc
    replace
    bbb
    replace
    eee
    aaa
    */
    
  • synchronizedXXX(XXX c) 返回由指定集合支持的同步(线程安全)集合

    例如List:

            List<String> list1 = Arrays.asList("ccc", "ddd", "bbb", "ddd","eee","aaa", "ddd");
            List<List<String>> lists = Collections.singletonList(list1);
    
      List<String> list1 = Arrays.asList("ccc", "ddd", "bbb", "ddd","eee","aaa", "ddd");
        int ddd = Collections.frequency(list1, "ddd");
        System.out.println(ddd);    //3
    
    
    
  • replaceAll(List list, T oldVal, T newVal) 将列表中一个指定值的所有出现替换为另一个。

            List<String> list1 = Arrays.asList("ccc", "ddd", "bbb", "ddd","eee","aaa", "ddd");
            Collections.replaceAll(list1,"ddd","replace");
            for (String s: list1) {
                System.out.println(s);
            }
    /*输出:
    ccc
    replace
    bbb
    replace
    eee
    aaa
    */
    
  • synchronizedXXX(XXX c) 返回由指定集合支持的同步(线程安全)集合

    例如List:

            List<String> list1 = Arrays.asList("ccc", "ddd", "bbb", "ddd","eee","aaa", "ddd");
            List<List<String>> lists = Collections.singletonList(list1);
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值