今天学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)