title: Java创建List、Map等集合对象的同时进行赋值操作

date: 2019-11-28 23:25:47

tags: JavaSE

categories: JavaSE


问题简介

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

int[] num = {1,2,3};
String strs = {"a", "b", "c"}

  但是,如果我们创建List集合,或者Map集合时,也想快速地为它赋初始值,应当如何做呢?

解决方式

方式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 // 代码2
String[] str = {"a","b","c"};
List<String> list = Arrays.asList(str);
str[0] = "e"; // 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");} };

  乍一看是不是有点懵逼,我们将这段代码展开来看,就会清晰很多:

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

  这下应该比之前容易理解了。这段代码就是创建了一个匿名内部类对象,且这个类继承自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(这里和匿名内部类的机制有关,就不详细叙述了)。所以在代码中,如果对对象的类型有着严格的要求,就需要谨慎考虑是否应该使用这种方式。

博客总结

  在平常编写代码时,还是第一种方式使用的比较多,因为简单而且不容易产生问题;而第二种方,我个人建议还是少用(虽然我就是为第二种方式写的博客.....),因为在类型要求严格的程序中,可能会产生问题。当然,第二种方式真的非常机智(感叹),而且可以用在各种类型的集合上,学习一下还是很有帮助的。

参考文献

《Java核心技术 卷Ⅰ》

Java创建List、Map等集合对象的同时进行赋值操作的更多相关文章

  1. java IO之 序列流 集合对象Properties 打印流 流对象

    序列流 也称为合并流. SequenceInputStream 序列流,对多个流进行合并. SequenceInputStream 表示其他输入流的逻辑串联.它从输入流的有序集合开始,并从 第一个输入 ...

  2. java创建TXT文件并进行读、写、修改操作

    import java.io.*; /**  *   * 功能描述:创建TXT文件并进行读.写.修改操作  *        * @author <a href="mailto:zha ...

  3. java基础复习之对于String对象,能够使用“=”赋值,也能够使用newkeyword赋值,两种方式有什么差别?

    String类型是实际工作中经经常使用到的类型,从数据类型上划分,String是一个引用类型,是API中定义的一个类.所以String类型的对象能够用new创建,比如String name=new S ...

  4. Java入门教程十二(集合与泛型)

    在 Java 中数组的长度是不可修改的.然而在实际应用的很多情况下,无法确定数据数量.这些数据不适合使用数组来保存,这时候就需要使用集合. Java 的集合就像一个容器,用来存储 Java 类的对象. ...

  5. Java基础知识强化之集合框架笔记53:Map集合之Map集合的遍历 键值对对象找键和值

    1. Map集合的遍历(键值对对象找键和值) Map -- 夫妻对  思路:  A: 获取所有结婚证的集合  B: 遍历结婚证的集合,得到每一个结婚证  C: 根据结婚证获取丈夫和妻子 转换:  A: ...

  6. java 创建匿名对象及声明map list时初始化

    java 创建匿名对象 类似于c# 中的 new { a:"aaa",b:"bbb"}; 1 创建匿名对象Object myobj = new Object() ...

  7. JSon_零基础_003_将Map集合对象转换为JSon格式的对象字符串,返回给界面

    将Map集合对象转换为JSon格式的对象字符串,返回给界面 需导入的jar包: 编写servlet: package com.west.webcourse.servlet; import java.i ...

  8. Java之数组array和集合list、set、map

    之前一直分不清楚java中的array,list.同时对set,map,list的用法彻底迷糊,直到看到了这篇文章,讲解的很清楚. 世间上本来没有集合,(只有数组参考C语言)但有人想要,所以有了集合 ...

  9. Java基础知识强化之集合框架笔记59:Map集合之TreeMap(TreeMap<String,String>)的案例

    1. TreeMap类的概述: 键是红黑树结构,可以保证键的排序和唯一性. 2. TreeMap案例: TreeMap<String, String> 代码示例: package cn.i ...

随机推荐

  1. HDU 6697 Closest Pair of Segments (计算几何 暴力)

    2019 杭电多校 10 1007 题目链接:HDU 6697 比赛链接:2019 Multi-University Training Contest 10 Problem Description T ...

  2. SDUTOJ 2498 数据结构实验之图论十一:AOE网上的关键路径

    题目链接:http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/2498.html 题目大意 略. 分析 ...

  3. 你真的懂return吗?

    递归算法中什么时候用return啥时候不用呢? 使用2个例子来说明:快速排序和二分查找 # 二分查找def binarySearch (arr, l, r, x): # 基本判断 if r >= ...

  4. Python 操作excel常见异常

    一.使用xlrd模块读取excel: 1.报错:IndexError: list index out of range,如下图 解决方法:reading_sheet.cell(1,0).value中c ...

  5. JasperReports入门,JasperReports是什么?

    Jasper报表 报表开发过程中面临的常见故障归纳在以下几点: 核心变化:为了反映业务发生变化或改进它通常以改变报告的核心逻辑. 结果输出:有各种各样的格式,报表可导出到如:HTML,文本,PDF,M ...

  6. 教你如何有效防止DDos攻击?

    DDos又称分布式拒绝服务,DDos是利用大量合理的请求造成资源过载,导致服务不可用.就比如一个餐馆总共有100个座位,突然有一天某个商家恶意竞争,雇佣了200个人来到这个餐馆坐着不吃不喝,门口还排着 ...

  7. SSL/TLS工作原理

    以前已经介绍过HTTP协议和HTTPS协议的区别,这次就来了解一下HTTPS协议的加密原理. 为了保证网络通信的安全性,需要对网络上传递的数据进行加密.现在主流的加密方法就是SSL (Secure S ...

  8. CodeForces祝贺上紫

    还是靠手速了. 不少比赛,经常差几分钟/一个细节就能AC一道比较难的题目. 加油! P.S 只能当成休闲性质,不能再当成正业了.迈向科研...

  9. wordpress添加视频弹窗插件Video PopUp

    Video PopUp 给外部div 添加class类名:class="main-play" a链接添加  class="vp-a" 测试链接地址:https: ...

  10. Spring Data之Example<>

    简单CRUD之Example动态查询 简单介绍 (部分口水话,部分来自网络,代码永远自产) 使用过Spring全家桶的各位大佬应该都知道,Spring Data这个是Spring对持久层框架的封装,比 ...