List是列表(接口),是可以允许出现重复值的,
Set是集合,不允许出现重复值
ArrayList(一般类)实现list接口
arraylist与vector是差不多的,只不过arraylist是不同步的,而vector是同步的
vector ArrayList其实都是数组的封装
如果不涉及多线程 使用ArrayList效率会高一点。
List接口
List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。
和下面要提到的Set不同,List允许有相同的元素。
除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个 ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。
实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。
ArrayList类
ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。
size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。
每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。
和LinkedList一样,ArrayList也是非同步的(unsynchronized)。
1.
List是接口,List特性就是有序,会确保以一定的顺序保存元素.
ArrayList是它的实现类,是一个用数组实现的List.
2.
一般情况下,如果没有必要,推荐代码只同List,Map接口打交道.
比如:List list = new ArrayList();
这样做的原因是list就相当于是一个泛型的实现,如果想改变list的类型,只需要:
List list = new LinkedList();//LinkedList也是List的实现类,也是ArrayList的兄弟类
这样,就不需要修改其它代码,这就是接口编程的优雅之处.
不过现在已经有List泛型的定义了,你可以决定List里面装什么类型的数据。
3.
如果开发的时候觉得ArrayList,HashMap的性能不能满足你的需要,可以通过实现List,Map(或者Collection)来定制你的自定义类.
可以参考The Art Of Computer Programming的Sorting and Searching部分
其实往往这些集合已经够用了,没必要去自己手动定制。
Vector类(此类已经被放弃,不建议使用,作为了解)
Vector类中的所有方法都是线程同步的,两个线程并发访问Vector时对象是安全的。但只有一个线程访问Vector对象时,因为源程序仍调用了同步方法,需要额外的监视器检查,运行效率要低些。
ArrayList类中的所有方法都是同步的,所有在没有多线程安全问题的时候,最好用ArrayList,程序的效率会高些。
在有线程安全问题,且我们的程序又没有自己处理的时候,只能用Vector。
Vector只能容纳object freforences不能容纳基本类型
Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。
当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小,这样,ArrayList就有利于节约内存空间。
HashSet类
1.如何保证无序不重复
Java中每一个对象都对应一个int型的哈希码,在向HashSet添加元素时,JVM会通过对象的HashCode()方法获取此对象的哈希码,然后对某一个整数(hashSet的初始容量)求余,将这个元素放在Set中位于模数的位置。如果该位置已存在元素,即出现要把两个元素放在同一位置的时候,如s1和s2,会判断s1.equal(s2),如果值为真,说明s1和s2相同,抛弃等放入的元素。如果为假,继续遍历set里面其它的元素,调用equals方法,确保没有相同的元素后,将s2放置在另一空闲位置。为了实现及达到性能保障,应尽量做到:1).一定要保证相同对象的哈希码相同2).尽量保证不同的对象返回不同的哈希码,以尽可能保证求余后的模数相等,而减少equals的调用。但是应注意:我们永远无法保证不同的对象的哈希码就一定不同(因为哈希码是int型的,当我们申请的对象个数比int型的数据还要多时,出现相同的情况是必然)
2.初始容量和加载因子的概念
无参的构造方法生成的HashSet对象,其底层HashMap实例的默认初始容量是16,加载因子是0.75,当向hashSet中加入对象时,随着对象个数的增多,会导致模数相同的可能性越来越大,也就是需要调用equal()方法的可能性越来越大,这就导致了很多不必要的开销,为了解决这一问题,Sun公司提出了加载因子的概念,即当hashSet尚未填满时(只需达到默认初始容量*加载因子,即16*0.75),就可以动态扩大容量,(增大为原容量的2倍,即32),这样哈希码就不再是对16求模了,而是对32求模,通过多开辟空间有效地降低了时间复杂度。
3.性能分析
HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证集合的迭代顺序,特别是它不保证该顺序恒久不变。此类允许使用null元素。此类为基本操作提供了稳定性能,这些基本操作包括add、remove、contains和size,假定哈希函数将这些元素正确地颁在桶中。对此集合进行迭代所需的时间与HashSet实例的大小(元素的数量)和底层HashMap实例(桶的数量)的"容量"的和成比例。因此,如此迭代性能很重要,则不要将寝容量设置得太高(或将加载因子设置得太低).
4.同步分析
注意,此实现不是同步的。 如果多个线程同时访问一个集合,而其中至少一个线程修改了该集合,那么它必须保持外部同步。这通常是通过对自然封装该集合的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSet 方法来“包装”集合。最好在创建时完成这一操作,以防止对 HashSet 实例进行意外的不同步访问:Set s = Collections.synchronizedSet(new HashSet(...));
5.避免内存泄露
在下面的实例中,如下操作 s1.age=21; test.remove(s1);并没有真正删除s1,这是因为在Student的hashcode方法中利用age来获取哈希值,当s1在加入哈希表之后,再对age(或name)进行修改,将会改变对象的原哈希值,哈希表会根据变动调整对象的位置,而remove方法仍在试图删除原位置的对象(此时可能已经为空),最终的结果是根本没有删除成功。这样做很可能会导致大量的无效对象(而程序员误认为此类对象已经游离,可以被GC回收)存在于set中,从而导致内存泄露。如在本例中,s1 = new Student("Pato",16);之后,s1原来指向的对象,GC不会做回收操作。
6.HashSet为什么不能重复
<1>、HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束
<2>、HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的 String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例.
7.实例
import java.util.HashSet;
import java.util.Set;
/**
*
* @author 钱亮亮
*
*/
public class SetTest {
public static void main(String[] args){
//无参的构造方法生成的HashSet对象,其底层HashMap实例的默认初始容量是16,加载因子是0.75
Set<Student> test = new HashSet<Student>();
Student s1 = new Student("Mary",18);
Student s2 = new Student("Charles",20);
Student s3 = new Student("Herry",18);
test.add(s1);
test.add(s2);
test.add(s3);
System.out.println("Size of Initial: " + test.size());//3
System.out.println(test);//[Student: Charles , 20, Student: Mary , 18, Student: Herry , 18]
test.remove(s1);
System.out.println("Size of Removed: " + test.size());//2
System.out.println(test);//[Student: Charles , 20, Student: Herry , 18]
test.add(s1);
System.out.println("Size of Added: " + test.size());//3
System.out.println(test);//[Student: Charles , 20, Student: Mary , 18, Student: Herry , 18]
s1.age = 21;
test.remove(s1);
System.out.println("Size of Update-Remove: " + test.size());//3 *************************remove失效
System.out.println(test);//[Student: Charles , 20, Student: Mary , 21, Student: Herry , 18]
s1 = new Student("Pato",16);
test.add(s1);
System.out.println("Size of Added: " + test.size());//4
System.out.println(test);//[Student: Charles , 20, Student: Mary , 21, Student: Pato , 16, Student: Herry , 18]
}
}
class Student{
public String name;
public int age;
public Student(){}
public Student(String name, int age){
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if(this == obj) return true;
if(obj == null) return false;
if(!(obj instanceof Student)) return false;
Student s = (Student)obj;
if(this.name.equalsIgnoreCase(s.name)&&this.age==s.age) return true;
else return false;
}
@Override
public int hashCode() {
return name.toLowerCase().hashCode()+age;
}
@Override
public String toString() {
return "Student: "+name+" , "+age;
}
}
分享到:
相关推荐
详细描述map、list、set的常用子类特性,各个场景的适用。
6.JUC并发工具类在大厂的应用场景详解 (1).pdf 7、深入理解 AQS 独占锁之 Reentrantlock 源码分析 (1).pdf ...9、并发容器 (Map、List、Set) 实战及其原理.pdf 10、阻塞队列BlockingQueue 实战及其原理分析.pdf
Java集合Collection、List、Set、Map使用详解
Java集合Collection、List、Set、Map使用详解
前端框架Dart的集合类型List Set Map详解 以及循环语句 forEach map where any every详解,包括PPT和源码
Java集合Collection、List、Set、Map使用详解.pdf
Java集合Collection、List、Set、Map使用详解.doc
java集合collection、list、set、map使用详解.doc
在学习python基础过程中,整理的python中list与tuple,dict与set区别,
java各种集合的详解Set,List,Vector,arrayList,linkList,HashSet
java集合的详解,collection,list,set,map疑难解答,对于对容器似懂非懂的新手来说,这无疑是给你指点迷津的一个非常不错的选择,讲解内容丰富。
Java集合排序及java集合类详解 (Collection, List, Set, Map)
01_Python基本语法 基本语法&数据类型&运算符详解 02_Python常见数据类型Number,String,Tuple详解 03_Python常见数据类型List&dict&set 04_Python常见数据类型(三) 05_Python常见流程控制&循环结构
6.JUC并发工具类在大厂的应用场景详解 (1).pdf 7、深入理解 AQS 独占锁之 Reentrantlock 源码分析 (1).pdf ...9、并发容器 (Map、List、Set) 实战及其原理.pdf 10、阻塞队列BlockingQueue 实战及其原理分析.pdf
Java集合排序及java集合类详解(Collection、List、Map、Set)