1、需求描述:

        在Java当中,若希望在创建数组的同时给数组赋值很简单,可以想下面这样:

        int[] num = {1,2,3};

"a", "b", "c"}

        但是创建一个List、Set、Map的同时该如何进行赋值操作呢?

2、解决方法:

        1、方法一:调用函数方法

ArrayList<String> list = new ArrayList<>(Arrays.asList("aa", "bb", "cc"));

                  Arrays.asList(T... a) 方法的参数是一个可变长参数,也就是说他能够传入一个数组,也能够传入多个参数,而它的作用就是将传入的数组或多个数据封装成List集合返回,而上面的代码就是接收返回的List集合,并将其作为参数传入ArrayList的构造方法,创建一个新的ArrayList对象。

                扩展:为什么不能直接将asList方法的返回值赋给list参数,而要将它传入构造器创建新的对象呢?


// 代码1

List<String> list1 = Arrays.asList("aa", "bb", "cc"); 
  
 
  

    list1.add("dd");// UnsupportedOperationException 操作list1时会抛异常

// 代码2

String[] str = {"a","b","c"}; 
  
 
  

    List<String> list = Arrays.asList(str); 
  
 
  

    str[0] = "e"; //修改数组的0号数值时, list中的0号位置也一同改变


                 首先代码1,使用asList方法返回的创建的List对象,不允许进行修改操作,否则将会抛出一个UnsupportedOperationException;再来看代码2,我们将一个数组作为asList的参数,得到一个List对象,但是此时我们改变这个数组中元素的值,list对象的值也会发生改变,因为这个List对象底层引用的就是这个数组,并且和代码1一样,这个list也不能修改。

                 但是,若我们将返回的List对象作为参数传入ArrayList的构造器中,这个问题就不会发生,因为ArrayList的构造器将会把传入的list中所有的元素复制一份,因此不会影响到原数组,且可以随意改变。

        2、方法二:匿名内部类

List<String> list = new ArrayList<String>(){ {add("a"); add("b"); add("c");} };

        这个方法它可以用在任意一种集合类型上(Map,Set......)

            这下应该比之前容易理解了。这段代码就是创建了一个匿名内部类对象,且这个类继承自ArrayList,在这个匿名内部类中添加了一个非静态代码块,并在代码块中调用了三次add方法,为这个List对象赋值。

          我们知道,若我们想创建一个对象,可以直接new 构造方法,但是我们若想写一个匿名内部类,这个匿名内部类继承自某个类,只需在构造方法后面加上一对大括号。同时,非静态代码块会在构造方法执行前被执行,所以我们将赋值语句放在了代码块中,于是就有了上面这段代码。若还是看不明白,没关系,看下面这段代码十有八九就明白了,我们将上面的代码换另一种方式写出来:

public class Test {
        public static void main(String[] args) {
                List<String> list = new MyList();
        }
}
// 创建一个类继承自ArrayList
class MyList extends ArrayList{
// 在类的非静态代码块中编写赋值语句
        {
        add("a");
        add("b");
        add("c");
        }
}

  以上代码就是最开始那句代码的完整版,创建一个MyList类(名字随意),继承自ArrayList,并编写一个非静态代码块调用三次add方法,这个代码块将会在构造方法执行前被执行,因此创建一个MyList对象后,它肯定已经有三条数据了。若到此时还没有听懂,可能就需要去了解一下匿名内部类,以及代码块的执行机制了。

这种为集合赋值的好处就是,它可以用在任意一种集合类型上(Map,Set......),如下代码:

// 使用此方法为map赋值
HashMap<String, Integer> map = new HashMap<String, Integer>() {
        {
        put("a", 1); put("b", 2); put("c", 3);
        }
};

  当然,这种方法也有一些弊端,就拿ArrayList来说,那就是这种方法得到的对象,它的类型并不是ArrayList,我们调用对象.getClass().getName()方法获取对象的类名,得到的是代码所在类的类名+$1(这里和匿名内部类的机制有关,就不详细叙述了)。所以在代码中,如果对对象的类型有着严格的要求,就需要谨慎考虑是否应该使用这种方式。