List集合和数组的相互转换

今天学FilenameFilter的时候,看源码产生了一个问题

import java.io.File;
import java.io.FilenameFilter;

public class Test3 {
	public static void main(String[] args) {
		File dir = new File("E:\\");
		String[] arr = dir.list(new FilenameFilter() {
			@Override
			public boolean accept(File dir, String name) {
				File file = new File(dir, name);
				return file.isFile() && file.getName().endsWith(".jpg");
			}
		});
		
		for (String string : arr) {
			System.out.println(string);
		}
	}

}
//看list方法的源码如下:
    public String[] list(FilenameFilter filter) {
        String names[] = list();
        if ((names == null) || (filter == null)) {
            return names;
        }
        List<String> v = new ArrayList<>();
        for (int i = 0 ; i < names.length ; i++) {
            if (filter.accept(this, names[i])) {
                v.add(names[i]);
            }
        }
        return v.toArray(new String[v.size()]);
    }

源码中的最后一句return v.toArray(new String[v.size()]);有点不太懂,现在来回顾一下List集合怎么转成数组:
查看List集合的API发现有两种转成数组的方法:
在这里插入图片描述

  • 第一种,toArray的不带参方法,其返回值类型为Object

示例:

package Test;

import java.util.ArrayList;
import java.util.List;

public class List_toArray {

	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("张三");
		list.add("李四");
		list.add("王五");
		
		Object[] array = list.toArray(); //注意用Object数组接收,否则会出现类型转换异常
		System.out.println(array);
	}

}
输出结果:
[Ljava.lang.Object;@15db9742
  • 第二种,toArray的带参方法,在创建数组的时候指定数组的长度,最好与集合size保持一致,否则集合长度大于数组长度,原数组将被重置为null

示例:

package Test;

import java.util.ArrayList;
import java.util.List;

public class List_toArray {

	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("张三");
		list.add("李四");
		list.add("王五");
		
		String[] string = new String[list.size()]; //先创建一个String类型的数组,和list集合长度一样
		list.toArray(string);
		//对数组进行遍历
		for (String str : string) {
			System.out.println(str);
		}
	}

}
输出结果:
张三
李四
王五

如果指定数组长度小于集合长度,我们看一下:

package Test;

import java.util.ArrayList;
import java.util.List;

public class List_toArray {

	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("张三");
		list.add("李四");
		list.add("王五");
		
		String[] string = new String[2]; //先创建一个String类型的数组,和list集合长度一样
		list.toArray(string);
		//对数组进行遍历
		for (String str : string) {
			System.out.println(str);
		}
	}

}
输出结果
null
null
这里变为null的原因可以从ArrayList集合的toArray看出:
    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            // Make a new array of a's runtime type, but my contents:
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }

关于ArrayList集合的toArray方法中的System.arraycopy(elementData, 0, a, 0, size);其实是:

ArrayList中元素的添加和删除操作都得依赖 System的arraycopy方法, System.arraycopy(a, 0, elementData, size, numNew);的意思是将数组a中从下标0开始,到0+numNew=numNew之间的元素移动到elementData数组中,但存放的位置是在size之后的,这样说应该能懂这个方法是干什么的了,这个操作是比较花时间的,这也说明添加和删除操作比较的频繁的时候,LinkedList是要好于ArrayList的.
所以System.arraycopy(elementData, 0, a, 0, size);这句话的意思就是将数组elementData中从下标0开始,到0+size=size之间的元素移动到a数组中.但存放的位置是从0开始的;
transient Object[] elementData;
存储ArrayList的元素的数组缓冲区。
ArrayList的容量是此数组缓冲区的长度。 添加第一个元素时,任何具有elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA的空ArrayList都将扩展为DEFAULT_CAPACITY。
//elementData是存放当前集合中所有的元素的一个数组

所以经上面就可以看出return v.toArray(new String[v.size()]);这句话意思其实就是:

String[] string = new String[v.size()]; 
return  v.toArray(string);
//return v.toArray(new String[v.size()])这里括号里面的四匿名对象
再看数组转集合

查看Arrays类的API发现:
在这里插入图片描述
这里的三个点是java1.5新特性,这三个点的学名叫做可变长参数,也就是相当于一个数组,能够传入0个至n个参数

	public static void main(String[] args) {
        String[] t1 = {};
        String[] t2 = {"java","C++"};
        String t3 = "java";
        threePoint("java","C++","Python");
        threePoint(t1);
        threePoint(t2);
        threePoint(t3);
        //threePoint(t3,t2);//类型错误,数组只能传一个
    }

    public static void threePoint(String... s) {
        if (s == null) {
            return;
        }
        int len = s.length;
        if (len == 0) {
            System.out.println("没有字符");
        } else {
            for (String s1 : s
            ) {
                System.out.println(s1 + " ");
            }
        }
        System.out.println("==============================");
    }

可以看出即可以直接传一个String,也可以直接传String[]的数组,更可以在传递参数时,用逗号把每一个参数隔开。但是由于三个点就代表数组类型,所以传数组的时候,就只能传一个参数,不能再用逗号传其他参数
此外还需要注意:"…“与数组参数又有区别,”…"表示可变长参数(多个参数),数组参数只是一个参数

public class Test {
	void t1(String... a) {
		System.out.println("t1");
		for (String s : a)
			System.out.printf(" " + s);
		System.out.println();
	}
 
	void t2(String[] a) {
		System.out.println("t2");
		for (String s : a)
			System.out.printf(" " + s);
		System.out.println();
	}
 
	public static void main(String[] args) {
		String a[] = { "a", "b", "d", "e", "f", "g" };
		Test t = new Test();
		t.t1(a);
		t.t2(a);
		// 区别
		t.t1();// 可不传
		// t.t2();//必须传参数,否则报错
		t.t1("1", "2", "3", "4");// 也可以一个一个的传,t2则不可以
	}
}
结果:
t1
 a b d e f g
t2
 a b d e f g
t1

t1
 1 2 3 4

转自:https://blog.csdn.net/DavidHuang2017/article/details/85269770
https://blog.csdn.net/zjgyjd/article/details/98883516
跑题了…

可以利用工具类Arrays 中的asList方法实现数组转集合
查看源码:

    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

asList返回的是一个Array的内部类,其并没有重写AbstractList集合中全部的方法,比如add,remove方法(这一点也可以反推出AbstractList抽象类中的add,remove方法肯定不是抽象方法).所以,在对返回的集合进行增删操作会出错,查看源码:

    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

    /**
     * @serial include
     */
    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);
        }
    }

现在写一个数组转集合的实例:

package Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class List_toArray {

	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("张三");
		list.add("李四");
		list.add("王五");
		
		String[] string = new String[list.size()]; //先创建一个String类型的数组,和list集合长度一样
		list.toArray(string);
		//对数组进行遍历
		for (String str : string) {
			System.out.println(str);
		}
		//string数组转集合
		List<String> list2 = Arrays.asList(string);
		System.out.println(list2);
		System.out.println(list2.get(0));
		list2.add("赵六"); //错误
		
	}

}
输出结果:
张三
李四
王五
[张三, 李四, 王五]
张三
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	at Test.List_toArray.main(List_toArray.java:25)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值