List,Set,Map的两种初始化赋值方式

 List
List<Integer> list2 = new ArrayList<Integer>();
for (int i=0;i<times;i++){
list2.add(i);
} List<Integer> list1 = new ArrayList<Integer>(){
{
for (int i=0;i<times;i++){
add(i);
}
}
};
 Map
Map<String,String> map = new HashMap<String,String>(){
{
put("14","我是14");
put("13","我是13");
put("12","我是12"); }
};

Set

Set<String> set = new HashSet<String>(){
{
add("a");
add("b");
add("c");
}
};

两种方式中显然直接在申明时赋值的写法比较优雅,在List后面的两个{{}}的意义是,第一层括号表示一个匿名内部类,第二层括号表示在生成的内部类构造时被初始化,将class文件反编译后可以看出,java将匿名内部类创建了两个类,子类中含有父类的引用

源代码
public class MyTest2 {
Map<String,String> map = new HashMap<String,String>(){
{
put("1","我是1");
put("2","我是2");
}
};
public static int index = 10;
public static void main(String[] args) {
List<String> list = new ArrayList<String>(10){
{
for (int i=0;i<index;i++){
add("a");
}
}
};
}
}
反编译后:
public class MyTest2
{
Map<String, String> map = new HashMap() {};
public static int index = 10; public static void main(String[] args)
{
List<String> list = new ArrayList(10) {};
}
}
final class MyTest2$2
extends ArrayList<String>
{
MyTest2$2(int x0)
{
super(x0);
for (int i = 0; i < MyTest2.index; i++) {
add("a");
}
}
}
class MyTest2$1
extends HashMap<String, String>
{
MyTest2$1(MyTest2 this$0)
{
put("1", "我是1");
put("2", "我是2");
}
}
可知,编译后生成的实际上是ArrayList和HashMap的子类,因此有些操作是不允许的。
  1. 此种方式是匿名内部类的声明方式,所以引用中持有着外部类的引用。所以当时串行化这个集合时外部类也会被不知不觉的串行化,当外部类没有实现serialize接口时,就会报错。(序列化)
  2. 上例中,其实是声明了一个继承自HashMap的子类。然而有些串行化方法,例如要通过Gson串行化为json,或者要串行化为xml时,类库中提供的方式,是无法串行化Hashset或者HashMap的子类的,从而导致串行化失败。解决办法:重新初始化为一个HashMap对象(串行化)
List<String> list = new ArrayList<String>(){
{ for (int i=0;i<index;i++){
add("item"+i);
}
}
};
Gson gson = new Gson();
String str1 = gson.toJson(new ArrayList<String>(list));
若不重新赋值,打印出来的结果是null,重新赋值后打印出的结果是正确的。(经过测试,使用list.toString()是可以返回正确结果的)
执行效率方面
分别用两种方式初始化一个有一亿个元素的ArrayList,比较两者的时间
 
@Test
public void testEffict1(){
long start = System.currentTimeMillis();
int times = 1000000000;
List<Integer> list1 = new ArrayList<Integer>(){
{
for (int i=0;i<times;i++){
add(i);
}
}
};
long t1 = System.currentTimeMillis();
System.out.println("第一种方式time:"+(t1-start));
}
@Test
public void testEffict2(){
int times = 1000000000;
long t1 = System.currentTimeMillis();
List<Integer> list2 = new ArrayList<Integer>(100000000);
for (int i=0;i<times;i++){
list2.add(i);
}
long end = System.currentTimeMillis();
System.out.println("第二种方式time:"+(end-t1));
}
 
第一种方式time:33566
第二种方式time:33331

可见两者在效率方面的差别不大

Java中容器的两种初始化方式比较的更多相关文章

  1. Java中String对象两种赋值方式的区别

    本文修改于:https://www.zhihu.com/question/29884421/answer/113785601 前言:在java中,String有两种赋值方式,第一种是通过“字面量”赋值 ...

  2. 细说java中Map的两种迭代方式

    曾经对java中迭代方式总是迷迷糊糊的,今天总算弄懂了.特意的总结了一下.基本是算是理解透彻了. 1.再说Map之前先说下Iterator: Iterator主要用于遍历(即迭代訪问)Collecti ...

  3. java中多线程的两种创建方式

    一丶继承Thread类实现多线程 第一步:继承Thread类第二步:重写run()方法第三步:创建继承了Thread类的对象 , 调用start()方法启动. //线程创建方式一 : /* 第一步:继 ...

  4. Java连载66-数组的两种初始化方式

    一.数组 1.数组中存储元素的类型是统一的,每一个元素在内存中所占用的空间大小是相同的,知道数组的首元素的内存地址,要查找的元素只要知道下标,就可以快速的计算出偏移量,通过首元素内存地址加上偏移量,就 ...

  5. JAVA高级架构师基础功:Spring中AOP的两种代理方式:动态代理和CGLIB详解

    在spring框架中使用了两种代理方式: 1.JDK自带的动态代理. 2.Spring框架自己提供的CGLIB的方式. 这两种也是Spring框架核心AOP的基础. 在详细讲解上述提到的动态代理和CG ...

  6. 【转载】JAVA中线程的两种实现方法-实现Runnable接口和继承Thread类

    转自: http://blog.csdn.net/sunguangran/article/details/6069317 非常感谢原作者,整理的这么详细. 在java中可有两种方式实现多线程,一种是继 ...

  7. Springboot中IDE支持两种打包方式,即jar包和war包

    Springboot中IDE支持两种打包方式,即jar包和war包 打包之前修改pom.xml中的packaging节点,改为jar或者war    在项目的根目录执行maven 命令clean pa ...

  8. java中线程分两种,守护线程和用户线程。

    java中线程分为两种类型:用户线程和守护线程. 通过Thread.setDaemon(false)设置为用户线程: 通过Thread.setDaemon(true)设置为守护线程. 如果不设置次属性 ...

  9. JAVA中单例模式的几种实现方式

    1 线程不安全的实现方法 首先介绍java中最基本的单例模式实现方式,我们可以在一些初级的java书中看到.这种实现方法不是线程安全的,所以在项目实践中如果涉及到线程安全就不会使用这种方式.但是如果不 ...

随机推荐

  1. [leetcode-557-Reverse Words in a String III]

    Given a string, you need to reverse the order of characters in each word within a sentence whilestil ...

  2. 16.如何做到webpack打包vue项目后,可以修改配置文件

    问题描述: 前端需要修改restful API的url,但是打包之后,配置文件找不到了,如果在npm run build 生成dist后,这个配置也被写死了,传到运行的前端服务器上后,假设某次,api ...

  3. 4.Smarty模板之间调用

    {include file="header.tpl" name="cai"}

  4. 【笔记】记一次.net语法await和async的异步编程实验与笔记。

    1.实践代码全记录: using System; using System.Collections.Generic; using System.Diagnostics; using System.Li ...

  5. 静态变量和Session

    静态变量: Application级别的,不同客户端访问同一个变量. Session:对于每个访问的客户端是独立的,都有一个唯一的SessionID.也就是说,不同客户端下,都可以有一个Session ...

  6. [Android FrameWork 6.0源码学习] Window窗口类分析

    了解这一章节,需要先了解LayoutInflater这个工具类,我以前分析过:http://www.cnblogs.com/kezhuang/p/6978783.html Window是Activit ...

  7. 从零搭建DotnetCore2.0

    右键解决方案>新建项目> 选择Web>ASP.NETCoreWeb应用程序(.NET Core) 选择Web应用程序,暂时不选择启用Docker,身份验证选择个人用户账户(会自动生成 ...

  8. 使用boost/property_tree进行XML操作

    之前一直用tinyxml来进行XML文件操作,刚刚接触的一个测试项目是使用boost操作的,虽然不清楚这两者的差异,但boost使用起来还挺方便的,所以简单整理一些关于boost解析和创建XML文件的 ...

  9. php与MySQL(php内置mysql函数)

    获取数据 在讲解下面的方法之前,我们首先来看一下我们的数据表的结构: mysqli_fetch_row()函数 mysqli_fetch_row()函数从结果集中取得一行,并以索引数组形式返回. 语法 ...

  10. AddDigitsTotal - 把数字中单个数相加

    给定一个int数字,把数字中的单个数相加起来:得到的结果如果不是个位数,继续相加 如给定 19,执行1+9 = 10 --> 1 + 0 = 1  返回1 给定22,返回4 思路很简单,把各个位 ...