set和list都是集合接口
简要说明
set --其中的值不允许重复,无序的数据结构。
list --其中的值允许重复,因为其为有序的数据结构。
List的功能方法
实际上有两种List:
一种是基本的ArrayList,其优点在于随机访问元素,另一种是更强大的LinkedList,它并不是为快速随机访问设计的,而是具有一套更通用的方法。
List :
次序是List最重要的特点:它保证维护元素特定的顺序。List为Collection添加了许多方法,使得能够向List中间插入与移除元素(这只推荐LinkedList使用。)一个List可以生成ListIterator,使用它可以从两个方向遍历List,也可以从List中间插入和移除元素。
ArrayList :
由数组实现的List。允许对元素进行快速随机访问,但是向List中间插入与移除元素的速度很慢。ListIterator只应该用来由后向前遍历ArrayList,而不是用来插入和移除元素。因为那比LinkedList开销要大很多。
LinkedList :
对顺序访问进行了优化,向List中间插入与删除的开销并不大。随机访问则相对较慢。(使用ArrayList代替。)还具有下列方法:addFirst(), 。
addLast(), getFirst(), getLast(), removeFirst() 和removeLast(), 这些方法 。
(没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。
Set的功能方法
Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面有两个不同的List。实际上Set就是Collection,只是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)Set不保存重复的元素(至于如何判断元素相同则较为负责)。
Set :
存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。加入Set的元素必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。
HashSet : 为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。
TreeSet : 保存次序的Set, 底层为树结构。使用它可以从Set中提取有序的序列。
LinkedHashSet : 。
具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。
Java的集合类都位于java.util包中,Java集合中存放的是对象的引用,而非对象本身。
Java集合主要分为三种类型:
a.Set(集):集合中的对象不按特定方式排序,并且没有重复对象。它的有些实现类能对集合中的对象按特定方式排序。
b.List(列表):集合中的对象按索引位置排序,可以有重复对象,允许按照对象在集合中的索引位置检索对象。
c.Map(映射):集合中的每一个元素包含一对键对象和值对象,集合中没有重复的键对象,值对象可以重复。它的有些实现类能对集合中的键对象进行排序。
Set、List和Map统称为Java集合。
1.Set(集)
Set集合中的对象不按特定方式排序,并且没有重复对象。Set接口主要有两个实现类HashSet和TreeSet。HashSet类按照哈希算法来存取集合中的对象,存取速度比较快。HashSet类还有一个子类LinkedHashSet类,它不仅实现了哈希算法,而且实现了链表数据结构。TreeSet类实现了SortedSet接口,具有排序功能。
Set的add()方法判断对象是否已经存在于集合中的判断流程:
boolean isExists = false;。
Iterator it = set.iterator();。
while(it.hasNext()){。
Object object = it.next();。
if(newObject.equals(oldObject)){。
isExists = true;。
break;
}
2.HashSet类
当HashSet向集合中加入一个对象时,会调用对象的hashCode()方法获得哈希码,然后根据这个哈希码进一步计算出对象在集合中的存放位置。
当Object1变量和object2变量实际上引用了同一个对象,那么object1和object2的哈希码肯定相同。
为了保证HashSet能正常工作,要求当两个对象用equals()方法比较的结果为相等时,它们的哈希码也相等。即:
customer1.hashCode() == customer2.hashCode();。
如:对应于Customer类的以下重写后的equals()方法:
public boolean equals(Object o){。
if(this==o) return true;。
if(!o instanceof Customer) return false;。
final Customer other = (Customer)o;。
if(this.name.equals(other.getName())&&this.age==other.getAge())。
return true;
else
return false;。
为了保证HashSet正常工作,如果Customer类覆盖了equals()方法,也应该覆盖hashCode()方法,并且保证两个相等的Customer对象的哈希码也一样。
public int hashCode(){。
int result;
result = (name==null?0:name.hashCode());。
result = 29*result+(age==null?0:age.hashCode());。
return result;。
3.TreeSet类
TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序。TreeSet支持两种排序方式:自然排序和客户化排序,在默认情况下TreeSet采用自然排序方式。
a.自然排序
在JDK中,有一部分类实现了Comparable接口,如Integer、Double和String等。Comparable接口有一个compareTo(Object o)方法,它返回整数类型。对于表达式x.compareTo(y),如果返回值为0,表示x和y相等,如果返回值大于0,表示x大于y,如果返回值小于0,表示x小于y。
TreeSet调用对象的compareTo()方法比较集合中对象的大小,然后进行升序排列,这种排序方式称为自然排序。
以下列出了JDK中实现了Comparable接口的一些类的排序方式。
类 排序。
BigDecimal\BigInteger\Byte\Double\Float\Integer\Long\Short 按数字大小排序。
Character 按字符的Unicode值的数字大小排序。
String 按字符串中字符的Unicode值排序。
使用自然排序时,只能向TreeSet集合中加入同类型的对象,并且这些对象的类必须实现了Comparable接口,否则会在第二次调用TreeSet的add()方法时,会抛出ClassCastException异常。
例如:
以下是Customer类的compareTo()方法的一种实现方式:
public int compareTo(Object o){。
Customer other = (Customer)o;。
//先按照name属性排序
if(this.name.compareTo(other.getName())>0) return 1;。
if(this.name.compareTo(other.getName())<0) return -1;。
//再按照age属性排序
if(this.age>other.getAge()) return 1;。
if(this.age<other.getAge()) return -1;。
return 0;
为了保证TreeSet能正确地排序,要求Customer类的compareTo()方法与equals()方法按相同的规则比较两个Customer对象是否相等。
因此在Customer类的equals()方法中应该采用相同的比较规则:
public boolean equals(Object o){。
if(this==o) return true;。
if(!(o instanceof Customer)) return false;。
final Customer other = (Customer)o;。
if(this.name.equals(other.getName())&&this.age==other.getAge()){。
return true;
}else{
return false;。
}
值得注意的是,对于TreeSet中已经存在的Customer对象,如果修改了它们的属性,TreeSet不会对集合进行重新排序。在实际域模型中,实体类的属性可以被更新,因此不适合通过TreeSet来排序。最适合于排序的是不可变类。
b.客户化排序
除了自然排序,TreeSet还支持客户化排序。java.util.Comparator接口用于指定具体的排序方式,它有个compare(Object object1,Object object2)方法,用于比较两个对象的大小。当表达式compare(x,y)的值大于0,表示x大于y;当compare(x,y)的值小于0,表示x小于y;当compare(x,y)的值等于0,表示x等于y。
例如:如果希望TreeSet仅按照Customer对象的name属性进行降序排列,可以创建一个实现Comparator接口的类CustomerComparator:
public class CustomerComparator implements Comparator{。
public int compare(Object o1,Object o2){。
Customer c1= (Customer)o1;。
Customer c2 = (Customer)o2;。
if(c1.getName().compareTo(c2.getName())>0) return -1;。
if(c2.getName().compareTo(c2.getName())<0) return 1;。
return 0;
}
接下来在构造TreeSet的实例时,调用它的TreeSet(Comparator comparator)构造方法:
Set set = new TreeSet(new CustomerComparator());。
4.向Set中加入持久化类的对象。
例如两个Session实例从数据库加载相同的Order对象,然后往HashSet集合里存放,在默认情况下,Order类的equals()方法比较两个Orer对象的内存地址是否相同,因此order1.equals(order2)==false,所以order1和order2游离对象都加入到HashSet集合中,但实际上order1和order2对应的是ORDERS表中的同一条记录。对于这一问题,有两种解决方案:
(1)在应用程序中,谨慎地把来自于不同Session缓存的游离对象加入到Set集合中,如:
Set orders = new HashSet();。
orders.add(order1);。
if(!order2.getOrderNumber().equals(order1.getOrderNumber()))。
order.add(order2);。
(2)在Order类中重新实现equals()和hashCode()方法,按照业务主键比较两个Order对象是否相等。
提示:为了保证HashSet正常工作,要求当一个对象加入到HashSet集合中后,它的哈希码不会发生变化。
5.List(列表)
List的主要特征是其对象以线性方式存储,集合中允许存放重复对象。List接口主要的实现类有LinkedList和ArrayList。LinkedList采用链表数据结构,而ArrayList代表大小可变的数组。List接口还有一个实现类Vector,它的功能和ArrayList比较相似,两者的区别在于Vector类的实现采用了同步机制,而ArrayList没有使用同步机制。
List只能对集合中的对象按索引位置排序,如果希望对List中的对象按其他特定方式排序,可以借助Comparator和Collections类。Collections类是集合API中的辅助类,它提供了操纵集合的各种静态方法,其中sort()方法用于对List中的对象进行排序:
a.sort(List list):对List中的对象进行自然排序。
b.sort(List list,Comparator comparator):对List中的对象进行客户化排序,comparator参数指定排序方式。
如Collections.sort(list);。
6.Map(映射)
Map(映射)是一种把键对象和值对象进行映射的集合,它的每一个元素都包含一对键对象和值对象,而值对象仍可以是Map类型,依次类推,这样就形成了多级映射。
Map有两种比较常用的实现:HashMap和TreeMap。HashMap按照哈希算法来存取键对象,有很好的存取性能,为了保证HashMap能正常工作,和HashSet一样,要求当两个键对象通过equals()方法比较为true时,这两个对象的hashCode()方法返回的哈希码也一样。
TreeMap实现了SortedMap接口,能对键对象进行排序。和TreeSet一样,TreeMap也支持自然排序和客户化排序两种方式。
例:创建一个缓存类EntityCache,它能粗略地模仿Session的缓存功能,保证缓存中不会出现两个OID相同的Customer对象或两个OID相同的Order对象,这种惟一性是由键对象的惟一性来保证的。
Key.java:
package mypack;。
public class Key{。
private Class classType;。
private Long id;。
public Key(Class classType,Long id){。
this.classType = classType;。
this.id = id;。
}
public Class getClassType(){。
return this.classType;。
}
public Long getId(){。
return this.id;。
}
public boolean equals(Object o){。
if(this==o) return true;。
if(!(o instanceof Key)) return false;。
final Key other = (Key)o;。
if(classType.equals(other.getClassType())&&id.equals(other.getId()))。
return true;。
return false;。
}
public int hashCode(){。
int result;
result = classType.hashCode();。
result = 29 * result + id.hashCode();。
return result;。
}
EntityCache.java:。
package mypack;。
import java.util.*;。
public class EntityCache {。
private Map entitiesByKey;。
public EntityCache() {。
entitiesByKey=new HashMap();。
}
public void put(BusinessObject entity){。
Key key=new Key(entity.getClass(),entity.getId());。
entitiesByKey.put(key,entity);。
}
public Object get(Class classType,Long id){。
Key key=new Key(classType,id);。
return entitiesByKey.get(key);。
}
public Collection getAllEntities(){。
return entitiesByKey.values();。
}
public boolean contains(Class classType,Long id){。
Key key=new Key(classType,id);。
return entitiesByKey.containsKey(key);。
}
list和set都是集合容器,list是有序不唯一 ,set是无序唯一 这两种集合主要看你需要封装什么样的数据。希望能帮到你!
Set和List都是接口,他们的取得都必须是实现了Collection接口和Iterable接口的类。只要是实现了这两个接口的类都就可以实现取得Set接口对象和List接口的目的。
我只用过Set,觉得他们用的地方不一样,所以应该是不能转换的。
真正要进行转换的话,就应当是用实现了Collection接口和Iterable接口的集合对象去取得这两个接口的对象吧。
一、List接口
List是一个继承于Collection的接口,即List是集合中的一种。List是有序的队列,List中的每一个元素都有一个索引;第一个元素的索引值是0,往后的元素的索引值依次+1。和Set不同,List中允许有重复的元素。实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。
ArrayList
ArrayList是一个动态数组,也是我们最常用的集合。它允许任何符合规则的元素插入甚至包括null。每一个ArrayList都有一个初始容量:
private static final int DEFAULT_CAPACITY = 10;。
随着容器中的元素不断增加,容器的大小也会随着增加。在每次向容器中增加元素的同时都会进行容量检查,当快溢出时,就会进行扩容操作。所以如果我们明确所插入元素的多少,最好指定一个初始容量值,避免过多的进行扩容操作而浪费时间、效率。
size、isEmpty、get、set、iterator 和 listIterator 操作都以固定时间运行。add 操作以分摊的固定时间运行,也就是说,添加 n 个元素需要 O(n) 时间(由于要考虑到扩容,所以这不只是添加元素会带来分摊固定时间开销那样简单)。
ArrayList擅长于随机访问。同时ArrayList是非同步的。
LinkedList
同样实现List接口的LinkedList与ArrayList不同,ArrayList是一个动态数组,而LinkedList是一个双向链表。所以它除了有ArrayList的基本操作方法外还额外提供了get,remove,insert方法在LinkedList的首部或尾部。
由于实现的方式不同,LinkedList不能随机访问,它所有的操作都是要按照双重链表的需要执行。在列表中索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端,节约一半时间)。这样做的好处就是可以通过较低的代价在List中进行插入和删除操作。
与ArrayList一样,LinkedList也是非同步的。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:
List list = Collections.synchronizedList(new LinkedList(…));。
Vector
与ArrayList相似,但是Vector是同步的。所以说Vector是线程安全的动态数组。它的操作与ArrayList几乎一样。
Stack
Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。
二、Set接口
Set是一个继承于Collection的接口,Set是一种不包括重复元素的Collection。它维持它自己的内部排序,所以随机访问没有任何意义。与List一样,它同样运行null的存在但是仅有一个。由于Set接口的特殊性,所有传入Set集合中的元素都必须不同,关于API方面。Set的API和Collection完全一样。实现了Set接口的集合有:HashSet、TreeSet、LinkedHashSet、EnumSet。
HashSet
HashSet堪称查询速度最快的集合,因为其内部是以HashCode来实现的。集合元素可以是null,但只能放入一个null。它内部元素的顺序是由哈希码来决定的,所以它不保证set的迭代顺序;特别是它不保证该顺序恒久不变。
TreeSet
TreeSet是二叉树实现的,基于TreeMap,生成一个总是处于排序状态的set,内部以TreeMap来实现,不允许放入null值。它是使用元素的自然顺序对元素进行排序,或者根据创建Set时提供的 Comparator 进行排序,具体取决于使用的构造方法。
LinkedHashSet
LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起 来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。
三、Map接口
Map与List、Set接口不同,它是由一系列键值对组成的集合,提供了key到Value的映射。在Map中它保证了key与value之间的一一对应关系。也就是说一个key对应一个value,所以它不能存在相同的key值,当然value值可以相同。实现map的集合有:HashMap、HashTable、TreeMap、WeakHashMap。
HashMap
以哈希表数据结构实现,查找对象时通过哈希函数计算其位置,它是为快速查询而设计的,其内部定义了一个hash表数组(Entry[] table),元素会通过哈希转换函数将元素的哈希地址转换成数组中存放的索引,如果有冲突,则使用散列链表的形式将所有相同哈希地址的元素串起来,可能通过查看HashMap.Entry的源码它是一个单链表结构。
HashTable
也是以哈希表数据结构实现的,解决冲突时与HashMap也一样也是采用了散列链表的形式。HashTable继承Dictionary类,实现Map接口。其中Dictionary类是任何可将键映射到相应值的类(如 Hashtable)的抽象父类。每个键和每个值都是一个对象。在任何一个 Dictionary 对象中,每个键至多与一个值相关联。Map是”key-value键值对”接口。 HashTable采用”拉链法”实现哈希表不过性能比HashMap要低。
TreeMap
有序散列表,实现SortedMap接口,底层通过红黑树实现。
WeakHashMap
谈WeakHashMap前先看一下Java中的引用(强度依次递减)
强引用:普遍对象声明的引用,存在便不会GC。
软引用:有用但并非必须,发生内存溢出前,二次回收。
弱引用:只能生存到下次GC之前,无论是否内存足够。
虚引用:唯一目的是在这个对象被GC时能收到一个系统通知。
以弱键实现的基于哈希表的Map。在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。丢弃某个键时,其条目从映射中有效地移除,因此,该类的行为与其他的 Map 实现有所不同。null值和null键都被支持。该类具有与HashMap类相似的性能特征,并具有相同的效能参数初始容量和加载因子。像大多数集合类一样,该类是不同步的。
四、总结
1、List、Set都是继承自Collection接口,Map则不是。
2、List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)
3、Set和List对比:
Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。
4、Map适合储存键值对的数据。
5、线程安全集合类与非线程安全集合类 :。
LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;。
HashMap是非线程安全的,HashTable是线程安全的;。
StringBuilder是非线程安全的,StringBuffer是线程安全的。
原文地址:http://www.qianchusai.com/javaset%E9%9B%86%E5%90%88%E5%92%8Clist.html