java中list与set有啥区别?

author author     2023-04-03     373

关键词:

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);

参考技术A 集合类型主要有3种:set(集)、bailist(列表)和map(映射)。
1、List(有序、可重复)
List里存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。
2、Set(无序、不能重复)

Set里存放的对象是无序,不能重复的,集合中的对象不按特定的方式排序,只是简单地把对象加入集合中。

3、Map(键值对、键唯一、值不唯一)

Map集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对map集合遍历时先得到键的set集合,对set集合进行遍历,得到相应的值。

java中list与set的区别

...制的,但是比较详细,楼主看看吧:ArrayListVectorLinkedList区别与用法ArrayList和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要设计到数组元素移... 查看详情

[知了堂学习笔记]_集合接口list与集合接口set的区别

在Java中除了Map以外的集合的根接口都是Collection接口,而在Collection接口的子接口中,最重要的莫过于List和Set集合接口。  今天我们就来谈谈List集合接口与Set集合接口的差异性。 查看List集合接口的接口方法    查看Set... 查看详情

java中set和list的区别

set和list都是集合接口简要说明set--其中的值不允许重复,无序的数据结构list--其中的值允许重复,因为其为有序的数据结构List的功能方法实际上有两种List:一种是基本的ArrayList,其优点在于随机访问元素,另一种是更强大的LinkedLi... 查看详情

`sorted(list)` 与 `list.sort()` 有啥区别?

】`sorted(list)`与`list.sort()`有啥区别?【英文标题】:Whatisthedifferencebetween`sorted(list)`vs`list.sort()`?`sorted(list)`与`list.sort()`有什么区别?【发布时间】:2014-04-2122:48:56【问题描述】:list.sort()对列表进行排序并替换原始列表,而sorted(l... 查看详情

java语言中集合与数组的区别是啥?

对JAVA的集合的理解是相对于数组,区别:1)数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型)2)JAVA集合可以存储和操作数目不固定的一组数据。3)JAVA集合只能存放引用类型的的数据,不能... 查看详情

list、set、map有啥区别和联系

1、List接口对Collection进行了简单的扩充,它的具体实现类常用的有ArrayList和LinkedList。你可以将任何东西放到一个List容器中,并在需要时从中取出。ArrayList从其命名中可以看出它是一种类似数组的形式进行存储,因此它的随机访... 查看详情

java中list,set和map的区别

List按对象进入的顺序保存对象,不做排序或编辑操作。Set对每个对象只接受一次,并使用自己内部的排序方法(通常,你只关心某个元素是否属于Set,而不关心它的顺序–否则应该使用List)。Map同样对每个元素保存一份,但这是基... 查看详情

scala中arraybuffer与array有啥区别

差异比较明显Array是定长的,按照文档说明为:Array[T]isScala'srepresentationforJava'sT[].Array存在下标越界访问的风险而List是变长的从效率上看,按下标访问Array快,List慢。在头部插入,Array慢,List快。参考技术Ascala中actor是简单... 查看详情

Java中的Collection和Set接口有啥区别?

】Java中的Collection和Set接口有啥区别?【英文标题】:WhatisthedifferencebetweenCollectionandSetinterfacesinJava?Java中的Collection和Set接口有什么区别?【发布时间】:2014-03-1706:04:50【问题描述】:声明的方法签名似乎是相等的。那么引入Set接... 查看详情

list和list之间有啥区别

list是有序的collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。与set不同,列表通常允许重复的元素。... 查看详情

listmapset的区别与联系

List、Map、Set的区别与联系一、结构特点List,Set都是继承自Collection接口,Map则不是;List和Set是存储单列数据的集合,Map是存储键值对这样的双列数据的集合;List中存储的数据是有顺序的,并且值允许重复;Map中存储的数据是无序... 查看详情

java中的list和set有什么区别

list与set方法的区别有:list可以允许重复对象和插入多个null值,而set不允许;list容器是有序的,而set容器是无序的等等Java中的集合共包含三大类,它们分别是Set(集),List(列表)以及Map&... 查看详情

java中的list和set有什么区别

list与set方法的区别有:list可以允许重复对象和插入多个null值,而set不允许;list容器是有序的,而set容器是无序的等等Java中的集合共包含三大类,它们分别是Set(集),List(列表)以及Map&... 查看详情

java集合框架中set和list的区别

1.Set接口实例存储的是无序的,不重复的数据。List接口实例存储的是有序的,可以重复的元素。2.Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。3.List和数组类似,可以... 查看详情

C++中set和map有啥区别

】C++中set和map有啥区别【英文标题】:WhatisthedifferencebetweensetandmapinC++C++中set和map有什么区别【发布时间】:2016-03-2417:43:12【问题描述】:考虑创建电话簿,但不知道哪个STL容器更好。请解释set和map之间的区别。在哪种情况下哪... 查看详情

java中json.tojsonstring(list,true);和json.tojsonstring(list);有啥区别呢,

需要导入两个jar包json-lib是用于转换json字符串的核心jar包,上面那个是辅助的。转换json数组就是JSONArray.fromObject(arrayList).toString();转换json对象就是JSONObject.fromObject(arrayList).toString();追问我问的是传这个true和不传有什么不同,参考... 查看详情

java中的list与set转换(代码片段)

一、List列表与Set列表的区别    List列表是有序、可以重复、线程不安全的列表,Set是无序、不能重复、线程不安全的列表。但List和Set可以通过方法来转换为线程安全的,加互斥锁。   Set<Long>set=newHashSet<>(); //... 查看详情

在java中,set集合和list集合有啥相同点和不同点???

在网上看到一点,可能对你有所帮助Set(集合):  Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。  Set介面主要实现了两个实现类:  HashSet : HashSet类按照哈希演算法来存取集合中... 查看详情