前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java中数组转集合总结

Java中数组转集合总结

作者头像
joshua317
发布2022-03-29 14:59:04
7740
发布2022-03-29 14:59:04
举报
文章被收录于专栏:技术博文技术博文

一、使用Arrays.asList() 方法

代码语言:javascript
复制
package com.joshua317;

import java.util.*;

public class Main {

    public static void main(String[] args) {
        String[] namesArr = {"joshua317","joshua318","joshua319"};
        List<String> namesLst = Arrays.asList(namesArr);
        for (String name: namesLst) {
            System.out.println(name);
        }
    }
}

对于Arrays.asList()方法需要注意以下几点: 1.该方法返回的是基于数组的List视图(List view)。所以,这种方式是将数组转换为List的最快的方式。因为返回的只是视图,不需要多余的内存来创建新的List以及复制操作。

2.该方法返回的List是长度是固定的(fixed),不是只读的。所以我们不能进行删除、添加操作,而可以使用set()方法进行修改元素操作。如果你对返回的List执行add()添加新元素,会返回UnsupportedOperationException。

代码语言:javascript
复制
package com.joshua317;

import java.util.*;

public class Main {

    public static void main(String[] args) {
        String[] namesArr = {"joshua317","joshua318","joshua319"};
        List<String> namesLst = Arrays.asList(namesArr);
        namesLst.add("joshua319");
        for (String name: namesLst) {
            System.out.println(name);
        }
    }
}

3.因为该方法返回的是基于原数组的List视图,所以,当我们使用set方法修改了List中的元素的时候,那么原来的数组也会跟着改变(这是视图的特性)。

代码语言:javascript
复制
package com.joshua317;

import java.util.*;

public class Main {

    public static void main(String[] args) {
        String[] namesArr = {"joshua317","joshua318","joshua319"};
        List<String> namesLst = Arrays.asList(namesArr);
        namesLst.set(0,"joshua320");
        System.out.println("==========list==========");
        for (String name: namesLst) {
            System.out.println(name);
        }
        System.out.println("==========array==========");
        for (String name: namesArr) {
            System.out.println(name);
        }
    }
}

4.从java 5开始,该方法支持泛型,所以我们可以从数组中得到类型安全ArrayList。

注意:

1.如果我们想让转换为只读的List,可以使用Collections.unmodifiableList()方法来将数组转换为指定List。

代码语言:javascript
复制
package com.joshua317;

import java.util.*;

public class Main {

    public static void main(String[] args) {
        String[] namesArr = {"joshua317","joshua318","joshua319"};
        final List<String> namesLst = Collections.unmodifiableList(Arrays.asList(namesArr));

        for (String name: namesLst) {
            System.out.println(name);
        }
    }
}

2.如果想返回的方法能够进行添加、删除元素操作,则可以使用new ArrayList(Arrays.asList(array)) ,这样就会创建一个对象类型的ArrayList,并将数组的内容拷贝过去。

代码语言:javascript
复制
package com.joshua317;

import java.util.*;

public class Main {

    public static void main(String[] args) {
        String[] namesArr = {"joshua317","joshua318","joshua319"};
        ArrayList<String> namesLst = new ArrayList<>(Arrays.asList(namesArr));
        namesLst.add("joshua320");

        for (String name: namesLst) {
            System.out.println(name);
        }
    }
}

二、使用Collections.addAll()方法

使用Collections.addAll()方法没有第一种方法高效,但是更加灵活。同样也是新建一个ArrayList,将数组的内容复制进去。

代码语言:javascript
复制
package com.joshua317;

import java.util.*;

public class Main {

    public static void main(String[] args) {
        String[] namesArr = {"joshua317","joshua318","joshua319"};
        ArrayList<String> namesLst = new ArrayList<>();

        Collections.addAll(namesLst, namesArr);
        namesLst.add("joshua320");

        for (String name: namesLst) {
            System.out.println(name);
        }
    }
}

对于Collections.addAll()方法:

1.没有Arrays.asList()快,但是更加灵活。

2.该方法实际上是将数组的内容复制到ArrayList中

3.因为是复制内容到ArrayList中,所以我们对ArrayList进行修改、添加、删除操作都不会影响原来的数组。

4.该方法相当于一个添加操作。该方法并不会覆盖ArrayList中已经存在的元素。

代码语言:javascript
复制
package com.joshua317;

import java.util.*;

public class Main {

    public static void main(String[] args) {
        String[] namesArr = {"joshua317","joshua318","joshua319"};
        ArrayList<String> namesLst = new ArrayList<>();

        Collections.addAll(namesLst, namesArr);
        namesLst.add("---------");
        Collections.addAll(namesLst, namesArr);

        for (String name: namesLst) {
            System.out.println(name);
        }
    }
}

三、使用ArrayList的构造方法

其实上面方法一中已经提到了,使用ArrayList的构造方法同时结合了Arrays.asList方法

代码语言:javascript
复制
package com.joshua317;

import java.util.*;

public class Main {

    public static void main(String[] args) {
        String[] namesArr = {"joshua317","joshua318","joshua319"};
        ArrayList<String> namesLst = new ArrayList<>(Arrays.asList(namesArr));
        namesLst.add("joshua320");

        for (String name: namesLst) {
            System.out.println(name);
        }
    }
}

ArrayList构造方法:

ArrayList(Collection < ? extends E > c) : 构造一个包含特定容器的元素的列表,并且根据容器迭代器的顺序返回。 所以构造方法所做的事情如下:

1.将容器c转换为一个数组

2.将数组拷贝到ArrayList中称为”elementData”的数组中

ArrayList的构造方法的源码如下:

代码语言:javascript
复制
  public ArrayList(Collection<? extends E> c) {
        Object[] a = c.toArray();
        if ((size = a.length) != 0) {
            if (c.getClass() == ArrayList.class) {
                elementData = a;
            } else {
                elementData = Arrays.copyOf(a, size, Object[].class);
            }
        } else {
            // replace with empty array.
            elementData = EMPTY_ELEMENTDATA;
        }
    }

四、使用ArrayList的addAll()方法

ArrayList的addAll()方法结合Arrays.asList方法使用

代码语言:javascript
复制
package com.joshua317;

import java.util.*;

public class Main {

    public static void main(String[] args) {
        String[] namesArr = {"joshua317","joshua318","joshua319"};
        ArrayList<String> namesLst = new ArrayList<>();

        namesLst.addAll(Arrays.asList(namesArr));
        namesLst.add("joshua320");

        for (String name: namesLst) {
            System.out.println(name);
        }
    }
}

ArrayList.addAll(Collection < ? extends E > c) : 构造一个包含特定容器的元素的列表,并且根据容器迭代器的顺序返回。基本上和构造方法的原理一样。 所以addAll方法所做的事情如下:

1.将容器c转换为一个数组

2.将数组拷贝到ArrayList中称为”elementData”的数组中

ArrayList的addAll方法的源码如下:

代码语言:javascript
复制
  public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

五、拓展

5.1 为何对Arrays.asList()返回的List进行添加、删除操作会报错,而set方法却可以使用?

来看下Arrays.asList()方法相关源代码

代码语言:javascript
复制
 public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }
    
private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }

        @Override
        public int size() {
            return a.length;
        }

        @Override
        public Object[] toArray() {
            return a.clone();
        }

        @Override
        @SuppressWarnings("unchecked")
        public <T> T[] toArray(T[] a) {
            int size = size();
            if (a.length < size)
                return Arrays.copyOf(this.a, size,
                                     (Class<? extends T[]>) a.getClass());
            System.arraycopy(this.a, 0, a, 0, size);
            if (a.length > size)
                a[size] = null;
            return a;
        }

        @Override
        public E get(int index) {
            return a[index];
        }

        @Override
        public E set(int index, E element) {
            E oldValue = a[index];
            a[index] = element;
            return oldValue;
        }

        @Override
        public int indexOf(Object o) {
            E[] a = this.a;
            if (o == null) {
                for (int i = 0; i < a.length; i++)
                    if (a[i] == null)
                        return i;
            } else {
                for (int i = 0; i < a.length; i++)
                    if (o.equals(a[i]))
                        return i;
            }
            return -1;
        }

        @Override
        public boolean contains(Object o) {
            return indexOf(o) != -1;
        }

        @Override
        public Spliterator<E> spliterator() {
            return Spliterators.spliterator(a, Spliterator.ORDERED);
        }

        @Override
        public void forEach(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            for (E e : a) {
                action.accept(e);
            }
        }

        @Override
        public void replaceAll(UnaryOperator<E> operator) {
            Objects.requireNonNull(operator);
            E[] a = this.a;
            for (int i = 0; i < a.length; i++) {
                a[i] = operator.apply(a[i]);
            }
        }

        @Override
        public void sort(Comparator<? super E> c) {
            Arrays.sort(a, c);
        }
    }

根据源码我们可以得知,Arrays.asList()方法返回的是个内部的ArrayList,这个类同样是AbstractList的一种实现。而该ArrayList就只有以下方法,并没有实现add和remove方法:

代码语言:javascript
复制
contain(Object)
get(int)
indexOf(Object)
set(int)
size()
toArray()
toArray(T[])

根本就没有add()和remove()方法。这个类由于是AbstractList的一种实现,AbstractList的add和remove方法会有异常抛出:

代码语言:javascript
复制
 /**
     * Appends the specified element to the end of this list (optional
     * operation).
     *
     * <p>Lists that support this operation may place limitations on what
     * elements may be added to this list.  In particular, some
     * lists will refuse to add null elements, and others will impose
     * restrictions on the type of elements that may be added.  List
     * classes should clearly specify in their documentation any restrictions
     * on what elements may be added.
     *
     * <p>This implementation calls {@code add(size(), e)}.
     *
     * <p>Note that this implementation throws an
     * {@code UnsupportedOperationException} unless
     * {@link #add(int, Object) add(int, E)} is overridden.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     * @throws UnsupportedOperationException if the {@code add} operation
     *         is not supported by this list
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this list
     * @throws NullPointerException if the specified element is null and this
     *         list does not permit null elements
     * @throws IllegalArgumentException if some property of this element
     *         prevents it from being added to this list
     */
    public boolean add(E e) {
        add(size(), e);
        return true;
    }

所以 当我们对返回的List执行add和remove方法时,就会报UnsupportedOperationException了。但是因为有set()方法,所以,我们可以修改返回的List。

5.2 我们说Arrays.asList()返回的是基于原数组的List视图, 而且修改List的元素时候,原数组的内容也会同时改变,这又是为何呢?

根据上面的代码,我们可以知道, 我们调用返回的ArrayList的set(),get(), indexOf(), contain(),size()这些方法,本质上都是去对原数组进行对应的操作。所以,我们改变返回的ArrayList中的内容的时候,原数组也会同时改变。这就是集合视图(collection view),集合了常用的方法。

5.3 为何返回的ArrayList的长度是固定的?还有为什么Arrays.asList()方法最快?

还是上面的代码,一般来说,ArrayList内部有一个对象类型数组作为实例变量来存放ArrayList中的数据。而上面的内部类中,ArrayList的这个实例变量就是a,而它只是将引用指向了原数组,并未将原数组的内容复制到a中。这样就没有进行复制操作,也没有创建新的数组对象,自然最快了。

同时,该内部类ArrayList并为提供add方法等方法,自然是无法修改ArrayList的长度。而且因为是直接将实例变量a指向原数组,我们知道数组一旦初始化后就没法修改它的大小了,所以原数组不能改变大小,自然返回的ArrayList的长度也不能改变长度,长度就只能是固定的。

本文为joshua317原创文章,转载请注明:转载自joshua317博客 https://www.joshua317.com/article/243

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-02-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、使用Arrays.asList() 方法
  • 二、使用Collections.addAll()方法
  • 三、使用ArrayList的构造方法
  • 四、使用ArrayList的addAll()方法
  • 五、拓展
    • 5.1 为何对Arrays.asList()返回的List进行添加、删除操作会报错,而set方法却可以使用?
      • 5.2 我们说Arrays.asList()返回的是基于原数组的List视图, 而且修改List的元素时候,原数组的内容也会同时改变,这又是为何呢?
        • 5.3 为何返回的ArrayList的长度是固定的?还有为什么Arrays.asList()方法最快?
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档