java中arraylist<>是啥写法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中arraylist<>是啥写法相关的知识,希望对你有一定的参考价值。
java 的arraylistjava 的arraylist_Java中ArrayList类详解
1、什么是ArrayList
ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处:
动态的增加和减少元素
实现了ICollection和IList接口
灵活的设置数组的大小
2、如何使用ArrayList
最简单的例子:
ArrayList List = new ArrayList();
for( int i=0;i <10;i++ ) //给数组增加10个Int元素
List.Add(i);
//..程序做一些处理
List.RemoveAt(5);//将第6个元素移除
for( int i=0;i <3;i++ ) //再增加3个元素
List.Add(i+20);
Int32[] values = (Int32[])List.ToArray(typeof(Int32));//返回ArrayList包含的数组
这是一个简单的例子,虽然没有包含ArrayList所有的方法,但是可以反映出ArrayList最常用的用法
3、ArrayList重要的方法和属性
1)构造器
ArrayList提供了三个构造器:
public ArrayList();
默认的构造器,将会以默认(16)的大小来初始化内部的数组
public ArrayList(ICollection);
用一个ICollection对象来构造,并将该集合的元素添加到ArrayList
public ArrayList(int);
用指定的大小来初始化内部的数组
2)IsSynchronized属性和ArrayList.Synchronized方法
IsSynchronized属性指示当前的ArrayList实例是否支持线程同步,而ArrayList.Synchronized静态方法则会返回一个ArrayList的线程同步的封装。
如果使用非线程同步的实例,那么在多线程访问的时候,需要自己手动调用lock来保持线程同步,例如:
ArrayList list = new ArrayList();
//...
lock( list.SyncRoot ) //当ArrayList为非线程包装的时候,SyncRoot属性其实就是它自己,但是为了满足ICollection的SyncRoot定义,这里还是使用SyncRoot来保持源代码的规范性
list.Add( “Add a Item” );
如果使用ArrayList.Synchronized方法返回的实例,那么就不用考虑线程同步的问题,这个实例本身就是线程安全的,实际上ArrayList内部实现了一个保证线程同步的内部类,ArrayList.Synchronized返回的就是这个类的实例,它里面的每个属性都是用了lock关键字来保证线程同步。
3)Count属性和Capacity属性
Count属性是目前ArrayList包含的元素的数量,这个属性是只读的。
Capacity属性是目前ArrayList能够包含的最大数量,可以手动的设置这个属性,但是当设置为小于Count值的时候会引发一个异常。
4)Add、AddRange、Remove、RemoveAt、RemoveRange、Insert、InsertRange
这几个方法比较类似
Add方法用于添加一个元素到当前列表的末尾
AddRange方法用于添加一批元素到当前列表的末尾
Remove方法用于删除一个元素,通过元素本身的引用来删除
RemoveAt方法用于删除一个元素,通过索引值来删除
RemoveRange用于删除一批元素,通过指定开始的索引和删除的数量来删除
Insert用于添加一个元素到指定位置,列表后面的元素依次往后移动
InsertRange用于从指定位置开始添加一批元素,列表后面的元素依次往后移动
另外,还有几个类似的方法:
Clear方法用于清除现有所有的元素
Contains方法用来查找某个对象在不在列表之中
其他的我就不一一累赘了,大家可以查看MSDN,上面讲的更仔细
5)TrimSize方法
这个方法用于将ArrayList固定到实际元素的大小,当动态数组元素确定不在添加的时候,可以调用这个方法来释放空余的内存。
6)ToArray方法
这个方法把ArrayList的元素Copy到一个新的数组中。
4、ArrayList与数组转换
例1:
ArrayList List = new ArrayList();
List.Add(1);
List.Add(2);
List.Add(3);
Int32[] values = (Int32[])List.ToArray(typeof(Int32));
例2:
ArrayList List = new ArrayList();
List.Add(1);
List.Add(2);
List.Add(3);
Int32[] values = new Int32[List.Count];
List.CopyTo(values);
上面介绍了两种从ArrayList转换到数组的方法
例3:
ArrayList List = new ArrayList();
List.Add( “string” );
List.Add( 1 );
//往数组中添加不同类型的元素
object[] values = List.ToArray(typeof(object)); //正确
string[] values = (string[])List.ToArray(typeof(string)); //错误
和数组不一样,因为可以转换为Object数组,所以往ArrayList里面添加不同类型的元素是不会出错的,但是当调用ArrayList方法的时候,要么传递所有元素都可以正确转型的类型或者Object类型,否则将会抛出无法转型的异常。
4、ArrayList与数组转换
例1:
ArrayList List = new ArrayList();
List.Add(1);
List.Add(2);
List.Add(3);
Int32[] values = (Int32[])List.ToArray(typeof(Int32));
例2:
ArrayList List = new ArrayList();
List.Add(1);
List.Add(2);
List.Add(3);
Int32[] values = new Int32[List.Count];
List.CopyTo(values);
上面介绍了两种从ArrayList转换到数组的方法
例3:
ArrayList List = new ArrayList();
List.Add( “string” );
List.Add( 1 );
//往数组中添加不同类型的元素
object[] values = List.ToArray(typeof(object)); //正确
string[] values = (string[])List.ToArray(typeof(string)); //错误
和数组不一样,因为可以转换为Object数组,所以往ArrayList里面添加不同类型的元素是不会出错的,但是当调用ArrayList方法的时候,要么传递所有元素都可以正确转型的类型或者Object类型,否则将会抛出无法转型的异常。
5、ArrayList最佳使用建议
这一节我们来讨论ArrayList与数组的差别,以及ArrayList的效率问题
1)ArrayList是Array的复杂版本
ArrayList内部封装了一个Object类型的数组,从一般的意义来说,它和数组没有本质的差别,甚至于ArrayList的许多方法,如Index、IndexOf、Contains、Sort等都是在内部数组的基础上直接调用Array的对应方法。
2)内部的Object类型的影响
对于一般的引用类型来说,这部分的影响不是很大,但是对于值类型来说,往ArrayList里面添加和修改元素,都会引起装箱和拆箱的操作,频繁的操作可能会影响一部分效率。
但是恰恰对于大多数人,多数的应用都是使用值类型的数组。
消除这个影响是没有办法的,除非你不用它,否则就要承担一部分的效率损失,不过这部分的损失不会很大。
3)数组扩容
这是对ArrayList效率影响比较大的一个因素。
每当执行Add、AddRange、Insert、InsertRange等添加元素的方法,都会检查内部数组的容量是否不够了,如果是,它就会以当前容量的两倍来重新构建一个数组,将旧元素Copy到新数组中,然后丢弃旧数组,在这个临界点的扩容操作,应该来说是比较影响效率的。
例1:比如,一个可能有200个元素的数据动态添加到一个以默认16个元素大小创建的ArrayList中,将会经过:
16*2*2*2*2 = 256
四次的扩容才会满足最终的要求,那么如果一开始就以:
ArrayList List = new ArrayList( 210 );
的方式创建ArrayList,不仅会减少4次数组创建和Copy的操作,还会减少内存使用。
例2:预计有30个元素而创建了一个ArrayList:
ArrayList List = new ArrayList(30);
在执行过程中,加入了31个元素,那么数组会扩充到60个元素的大小,而这时候不会有新的元素再增加进来,而且有没有调用TrimSize方法,那么就有1次扩容的操作,并且浪费了29个元素大小的空间。如果这时候,用:
ArrayList List = new ArrayList(40);
那么一切都解决了。
所以说,正确的预估可能的元素,并且在适当的时候调用TrimSize方法是提高ArrayList使用效率的重要途径。
4)频繁的调用IndexOf、Contains等方法(Sort、BinarySearch等方法经过优化,不在此列)引起的效率损失
首先,我们要明确一点,ArrayList是动态数组,它不包括通过Key或者Value快速访问的算法,所以实际上调用IndexOf、Contains等方法是执行的简单的循环来查找元素,所以频繁的调用此类方法并不比你自己写循环并且稍作优化来的快,如果有这方面的要求,建议使用Hashtable或SortedList等键值对的集合。
ArrayList al=new ArrayList();
al.Add("How");
al.Add("are");
al.Add("you!");
al.Add(100);
al.Add(200);
al.Add(300);
al.Add(1.2);
al.Add(22.8);
5)ToArray方法
这个方法把ArrayList的元素Copy到一个新的数组中。
使用ArrayList类
ArrayList类实现了List接口,由ArrayList类实现的List集合采用数组结构保存对象。数组结构的优点是便于对集合进行快速的随机访问,如果经常需要根据索引位置访问集合中的对象,使用由ArrayList类实现的List集合的效率较好。数组结构的缺点是向指定索引位置插入对象和删除指定索引位置对象的速度较慢,如果经常需要向List集合的指定索引位置插入对象,或者是删除List集合的指定索引位置的对象,使用由ArrayList类实现的List集合的效率则较低,并且插入或删除对象的索引位置越小效率越低,原因是当向指定的索引位置插入对象时,会同时将指定索引位置及之后的所有对象相应的向后移动一位,如图1所示。当删除指定索引位置的对象时,会同时将指定索引位置之后的所有对象相应的向前移动一位,如图2所示。如果在指定的索引位置之后有大量的对象,将严重影响对集合的操作效率。
就是因为用ArrayList类实现的List集合在插入和删除对象时存在这样的缺点,在编写例程06时才没有利用ArrayList类实例化List集合,下面看一个模仿经常需要随机访问集合中对象的例子。
在编写该例子时,用到了Java.lang.Math类的random()方法,通过该方法可以得到一个小于10的double型随机数,将该随机数乘以5后再强制转换成整数,将得到一个0到4的整数,并随机访问由ArrayList类实现的List集合中该索引位置的对象,具体代码如下:
src\com\mwq\TestCollection.Java关键代码:
public static void main(String[] args)
String a = "A", b = "B", c = "C", d = "D", e = "E";
List list = new ArrayList();
list.add(a); // 索引位置为 0
list.add(b); // 索引位置为 1
list.add(c); // 索引位置为 2
list.add(d); // 索引位置为 3
list.add(e); // 索引位置为 4
System.out.println(list.get((int) (Math.random() * 5))); // 模拟随机访问集合中的对象
我实际中的练习例子:
1 packagecode;2 importjava.util.ArrayList;3 importjava.util.Iterator;4 public classSimpleTest 5
6
7public static voidmain(String []args)8
9 ArrayList list1 = newArrayList();10 list1.add("one");11 list1.add("two");12 list1.add("three");13 list1.add("four");14 list1.add("five");15 list1.add(0,"zero");16 System.out.println("" + list1.size()+ "个元素");17 System.out.println("");18
19 ArrayList list2 = newArrayList();20 list2.add("Begin");21 list2.addAll(list1);22 list2.add("End");23 System.out.println("" + list2.size()+ "个元素");24 System.out.println("");25
26 ArrayList list3 = newArrayList();27 list3.removeAll(list1);28 System.out.println("");29
30 list3.add(0,"same element");31 list3.add(1,"same element");32 System.out.println("" + list3.size()+ "个元素");33 System.out.println("");34 System.out.println("");35 System.out.println("");36
37
38 System.out.println("");39 Iterator it =list3.iterator();40 while(it.hasNext())41 String str =(String)it.next();42 System.out.println("");43 44
45 System.out.println("");46 list3.set(0,"another element");47 list3.set(1,"another element");48 System.out.println("");49 //Object [] array =(Object[]) list3.toArray(new Object[list3.size()] );
50 Object [] array =list3.toArray();51 for(int i = 0; i < array.length ; i ++)52 String str =(String)array[i];53 System.out.println("array[" + i + "] = "+str);54 55
56 System.out.println("");57 list3.clear();58 System.out.println("");59 System.out.println("" + list3.size()+ "个元素");60
61 //System.out.println("hello world!");
62 63 参考技术A java arraylist<>用法
打开APP
weixin_39877898
关注
java arraylist<>用法_Java入门系列:实例讲解ArrayList用法 原创
2021-02-20 21:04:39
weixin_39877898
码龄5年
关注
本文通过实例讲解Java中如何使用ArrayList类。
Java.util.ArrayList类是一个动态数组类型,也就是说,ArrayList对象既有数组的特征,也有链表的特征。可以随时从链表中添加或删除一个元素。ArrayList实现了List接口。
大家知道,数组是静态的,数组被初始化之后,数组长度就不能再改变了。ArrayList是可以动态改变大小的。那么,什么时候使用Array(数组),什么时候使用ArrayList?答案是:当我们不知道到底有多少个数据元素的时候,就可使用ArrayList;如果知道数据集合有多少个元素,就用数组。
1.ArrayList构造函数
ArrayList类支持3个构造方法。
Arraylist()
这个构造方法构造了一个空的链表。
ArrayList(Collection extends E> c)
这个构造方法构造了一个包含指定元素集合的链表,注意,这里的字符E是一个标记,用来表示集合中元素的类型。至于具体是什么类型,需要你在使用这个构造方法的时候来指定。
ArrayList(int initialCapacity)
这是第三个构造方法,构造了一个指定大小但内容为空的链表。initialCapacity参数就是初始容量大小。
举例来说,如果你要创建一个空的数组链表,用来存放String类型的对象,那么你可以像下面这样做:
ArrayList list = new ArrayList();
如果你需要创建一个指定初始容量的数组链表,你可以像下面这样做:
ArrayList list = new ArrayList(7);
注意:ArrayList类只支持对象类型,不支持 基础数据类型。就是说ArrayList对象只能存放对象,不能存放基础数据类型的数据。
2.ArrayList常用方法
下面是总结了一些比较常用的ArrayList类成员方法:
增加元素到链表中
boolean add(Element e)
增加指定元素到链表尾部.
void add(int index, Element e)
增加指定元素到链表指定位置.
从链表中删除元素
void clear()
从链表中删除所有元素.
E remove(int index)
删除链表中指定位置的元素.
protected void removeRange(int start, int end)
删除链表中从某一个位置开始到某一个位置结束的元素。
获取链表中的元素
E get(int index)
获取链表中指定位置处的元素.
Object[] toArray()
获取一个数组,数组中所有元素是链表中的元素.(即将链表转换为一个数组)
修改某个元素
E set(int index, E element)
将链表中指定位置上的元素替换成新元素。 参考技术B ArrayList构造函数 ArrayList类支持3个构造方法。 Arraylist() 这个构造方法构造了一个空的链表。 ArrayList(Collection extends E> c) 这个构造方法...
2.
ArrayList常用方法 下面是总结了一些比较常用的ArrayList类成员方法: 增加元素到链表中 boolean add...
3.
ArrayList使用实例 1 import java.util.*;2 3 ...
如何在 Java 中制作 ArrayList<Integer> 的深层副本? [复制]
【中文标题】如何在 Java 中制作 ArrayList<Integer> 的深层副本? [复制]【英文标题】:How do I make a deep copy of an ArrayList<Integer> in Java? [duplicate] 【发布时间】:2017-06-23 08:29:06 【问题描述】:我基本上只是想对 1 和 0 进行深度复制,所以我可以使用布尔值,但我想知道如何在一般情况下为整数执行此操作。
private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> a)
ArrayList<Integer> newA = new ArrayList<>(a.size());
for (int i = 0; i < a.size(); i++)
int newInt = 0;
if (a.get(i) == 1)
newInt = 1;
newA.add(newInt);
return newA;
【问题讨论】:
既然整数是不可变的,为什么要深拷贝它们? 【参考方案1】:clone()
方法受Integer
类的保护,因此您不能在该类之外调用Integer.clone()
。您可以做的是创建一个 new
整数。
private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> old)
ArrayList<Integer> copy = new ArrayList<Integer>(old.size());
for(Integer i : old)
copy.add(new Integer(i));
return copy;
您可以通过执行以下操作来测试它是否有效:
public static void main (String[] args) throws java.lang.Exception
ArrayList<Integer> arr = new ArrayList<>();
for(int i = 0; i<5; i++)
arr.add(new Integer(i));
ArrayList<Integer> x = makeDeepCopyInteger(arr);
for(int i = 0; i<x.size(); i++)
if(arr.get(i) == x.get(i))
System.out.println("Same object");
else
System.out.println("Not the same object");
测试
Integer a = new Integer(1);
Integer b = new Integer(a);
System.out.println(a==b); // true
System.out.println(System.identityHashCode(a) == (System.identityHashCode(b))); // false;
Integer a = new Integer(1);
Integer b = a;
System.out.println(a==b); // true
System.out.println(System.identityHashCode(a) == (System.identityHashCode(b))); // true
所以从我的测试看来,要创建一个用于复制到新数组的新引用,您应该使用new Integer()
。 Integer
是一个不可变对象,但当 Integer
的值发生变化时,该引用也会发生变化。
【讨论】:
由于Integer
是不可变的,您不需要创建它的副本。
@Kayaman 我对此进行了一些测试,请参阅我的编辑。也许我很困惑,但由于不创建副本,它似乎保留了旧的参考。
这没有什么问题。由于Integer
的值不能改变,例如,如果您有1000 个列表都引用相同的17
并不重要。你的最后一段是错误的。由于Integer
是不可变的,所以它的值不能改变。【参考方案2】:
使用流来复制对象。易于阅读,适合 JIT。以下代码提供了一个列表副本,其中包含 Integer 对象副本。
private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> a)
return a.stream().map(val -> new Integer(val)).collect(toList());
复制除整数以外的自定义对象覆盖实现并调用clone()
return a.stream().map(MyObjectClass::clone).collect(toList());
您可以使用序列化到 json 来代替克隆。例如。在 BeanUtils.getCopy(sourceBean) 中使用 java-utils
【讨论】:
欢迎来到堆栈溢出 :-) 请看How to Answer。您应该提供一些信息为什么您的代码可以解决问题。仅代码答案对社区没有用处。【参考方案3】:您可以执行以下操作:
public static List<Integer> clone(List<Integer> source)
return source.stream()
.map( intObj -> new Integer(intObj.intValue()))
.collect(Collectors.toList());
或者,更老式的:
public static List<Integer> clone(List<Integer> source)
List<Integer> newList = new ArrayList<>();
for(Integer intObj : source)
newList.add(new Integer(intObj.intValue()));
return newList;
通过利用自动装箱/自动拆箱,可以缩短这两者。但我已经明确表示要绝对清楚发生了什么。
但是,这是一种毫无意义的练习 - 事实上,它会浪费内存并且不利于性能。 Integer
是不可变的,因此更好的引用指向Integer
的同一实例。因为Integer
不可能改变值,所以不可能通过共享实例造成任何伤害。
这适用于一般的不可变对象,这也是它们是好东西的原因。
作为初学者,您不太可能找到new Integer(...)
是一个好主意的情况(甚至Integer.valueOf(int i)
,尽管这可能会返回一个缓存实例)。如果您已经有Integer
,请使用您拥有的:
Integer oldVar = ... ;
Integer newVar = oldVar;
不变性意味着永远没问题。对newVar
的操作不可能破坏oldVar
,因为没有newVar.setValue(newValue)
。
如果您有int
,请直接使用它并允许Java 的自动装箱将其转换为Integer
:
int oldValue = ... ;
Integer newValue = oldValue ; // Java will automatically put this through
// Integer.valueOf(int i)
您提到您真的很想使用布尔值。您应该考虑使用BitSet
。
【讨论】:
【参考方案4】:您必须遍历列表中的项目并在之前克隆它们,然后将它们添加到新列表中,如下所述:
How to clone ArrayList and also clone its contents?
【讨论】:
以上是关于java中arraylist<>是啥写法的主要内容,如果未能解决你的问题,请参考以下文章
观察 MutableLiveData <ArrayList<Objects>> 的正确方法是啥?安卓