汉邦问答 / 问答 / 问答详情

java中 List 与Set 的区别

2023-06-28 09:42:24
TAG: is
tt白

复制的,但是比较详细,楼主看看吧:

ArrayList Vector LinkedList 区别与用法

ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要设计到数组元素移动等内存操作,所以索引数据快插入数据慢,Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差,LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快!

线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构。这些类均在java.util包中。本文试图通过简单的描述,向读者阐述各个类的作用以及如何正确使用这些类。

Collection

├List

│├LinkedList

│├ArrayList

│└Vector

│ └Stack

└Set

Map

├Hashtable

├HashMap

└WeakHashMap

Collection接口

Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List和Set。

所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。

如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:

Iterator it = collection.iterator(); // 获得一个迭代子

while(it.hasNext()) {

Object obj = it.next(); // 得到下一个元素

}

由Collection接口派生的两个接口是List和Set。

List接口

List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。

和下面要提到的Set不同,List允许有相同的元素。

除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。

实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。

LinkedList类

LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。

注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:

List list = Collections.synchronizedList(new LinkedList(...));

ArrayList类

ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。

size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。

每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。

和LinkedList一样,ArrayList也是非同步的(unsynchronized)。

Vector类

Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。

Stack 类

Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

Set接口

Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。

很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。

请注意:必须小心操作可变对象(Mutable Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。

Map接口

请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。

Hashtable类

Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。

添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。

Hashtable通过initial capacity和load factor两个参数调整性能。通常缺省的load factor 0.75较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。

使用Hashtable的简单示例如下,将1,2,3放到Hashtable中,他们的key分别是”one”,”two”,”three”:

Hashtable numbers = new Hashtable();

numbers.put(“one”, new Integer(1));

numbers.put(“two”, new Integer(2));

numbers.put(“three”, new Integer(3));

要取出一个数,比如2,用相应的key:

Integer n = (Integer)numbers.get(“two”);

System.out.println(“two = ” + n);

由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方法。hashCode和equals方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode()方法,能加快哈希表的操作。

如果相同的对象有不同的hashCode,对哈希表的操作会出现意想不到的结果(期待的get方法返回null),要避免这种问题,只需要牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。

Hashtable是同步的。

HashMap类

HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null key。,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。

WeakHashMap类

WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。

总结

如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。

如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。

要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。

尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。

同步性

Vector是同步的。这个类中的一些方法保证了Vector中的对象是线程安全的。而ArrayList则是异步的,因此ArrayList中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销。

数据增长

从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控制集合中的对象。当你向这两种类型中增加元素的时候,如果元素的数目超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。

使用模式

在ArrayList和Vector中,从一个指定的位置(通过索引)查找数据或是在集合的末尾增加、移除一个元素所花费的时间是一样的,这个时间我们用O(1)表示。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线形增长:O(n-i),其中n代表集合中元素的个数,i代表元素增加或移除元素的索引位置。为什么会这样呢?以为在进行上述操作的时候集合中第i和第i个元素之后的所有元素都要执行位移的操作。这一切意味着什么呢?

这意味着,你只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是其他操作,你最好选择其他的集合操作类。比如,LinkList集合类在增加或移除集合中任何位置的元素所花费的时间都是一样的?O(1),但它在索引一个元素的使用缺比较慢-O(i),其中i是索引的位置.使用ArrayList也很容易,因为你可以简单的使用索引来代替创建iterator对象的操作。LinkList也会为每个插入的元素创建对象,所有你要明白它也会带来额外的开销。

最后,在《Practical Java》一书中Peter Haggar建议使用一个简单的数组(Array)来代替Vector或ArrayList。尤其是对于执行效率要求高的程序更应如此。因为使用数组(Array)避免了同步、额外的方法调用和不必要的重新分配空间的操作。

大鱼炖火锅

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接口的一些类的排序方式

类 排序

BigDecimalBigIntegerByteDoubleFloatIntegerLongShort 按数字大小排序

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

}

}

wpBeta

1、List,Set都是继承自Collection接口

2、List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的)

3、List接口有三个实现类:LinkedList,ArrayList,Vector ,Set接口有两个实现类:HashSet(底层由HashMap实现),LinkedHashSet

FinCloud

List和Set都是接口。他们各自有自己的实现类,有无顺序的实现类,也有有顺序的实现类。

最大的不同就是List是可以重复的。而Set是不能重复的。

List适合经常追加数据,插入,删除数据。但随即取数效率比较低。

Set适合经常地随即储存,插入,删除。但是在遍历时效率比较低。

善士六合

List有序而且可以重复,Set是没有顺序但不可以重复。如何使用那得看实际应用。比如你在设计实体时,这个实体包含了另一个实体的属性,而且是一对多的关系,那么你在一的这方是如果设计多的那方的属性呢?你觉得用list还是用set合适呢?其实用哪个都可以,但实体都是需要持久化到数据库的,要知道数据库一般是不允许重复,所以设计时一般使用set。另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。

北营

有序可重复,使用list;无序不可重复使用set。一般开发中使用list

比如:

list.add("1");

list.add("1");

set.add("1");

set.add("1").

list的长度为2,而set的长度为1

人类地板流精华

List就是可以重复的集合。而Set是不可以重复的。

假如你输入1,2,2,4

那么在List集合中就有4个元素:1,2,2,4

但如果在Set集合中就只有3个元素了:1,2,4

meira

集合类型主要有3种:set(集)、bailist(列表)和map(映射)。

1、List(有序、可重复)

List里存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。

2、Set(无序、不能重复)

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

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

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

NerveM

List

控制的是一个数组,那么可以有重复的数据。

在integer的list中,添加4个3的话,会有4个元素在list中。

而set是不允许有重复的数据,所以如果set中添加4个3,只会有1个3.

set的一个用处是,假设你要在一个名单里面查找又没有名字相同的,就可以用set,

如果set中没有该名字,就存进set。如果有的话,说明找到了重复的。

set一般常用的是hashset,查询和插入效率为o(1)。

九万里风9

list存有序元素,可以重复,set存无序元素,不可重复

小白

5yjhhtrrhhhhh

Ntou123

看java文档吧.

西柚不是西游

线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构。这些类均在java.util包中。本文试图通过简单的描述,向读者阐述各个类的作用以及如何正确使用这些类。

Collection

├List

│├LinkedList

│├ArrayList

│└Vector

│ └Stack

└Set

Map

├Hashtable

├HashMap

└WeakHashMap

Collection接口

Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List和Set。

所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。

如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:

Iterator it = collection.iterator(); // 获得一个迭代子

while(it.hasNext()) {

Object obj = it.next(); // 得到下一个元素

}

由Collection接口派生的两个接口是List和Set。

List接口

List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。

和下面要提到的Set不同,List允许有相同的元素。

除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。

实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。

LinkedList类

LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。

注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:

List list = Collections.synchronizedList(new LinkedList(...));

ArrayList类

ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。

size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。

每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。

和LinkedList一样,ArrayList也是非同步的(unsynchronized)。

Vector类

Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。

Stack 类

Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

Set接口

Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。

很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。

请注意:必须小心操作可变对象(Mutable Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。

Map接口

请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。

Hashtable类

Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。

添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。

Hashtable通过initial capacity和load factor两个参数调整性能。通常缺省的load factor 0.75较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。

使用Hashtable的简单示例如下,将1,2,3放到Hashtable中,他们的key分别是”one”,”two”,”three”:

Hashtable numbers = new Hashtable();

numbers.put(“one”, new Integer(1));

numbers.put(“two”, new Integer(2));

numbers.put(“three”, new Integer(3));

要取出一个数,比如2,用相应的key:

Integer n = (Integer)numbers.get(“two”);

System.out.println(“two = ” + n);

由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方法。hashCode和equals方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode()方法,能加快哈希表的操作。

如果相同的对象有不同的hashCode,对哈希表的操作会出现意想不到的结果(期待的get方法返回null),要避免这种问题,只需要牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。

Hashtable是同步的。

HashMap类

HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null key。,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。

WeakHashMap类

WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。

总结

如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。

如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。

要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。

尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。

同步性

Vector是同步的。这个类中的一些方法保证了Vector中的对象是线程安全的。而ArrayList则是异步的,因此ArrayList中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销。

数据增长

从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控制集合中的对象。当你向这两种类型中增加元素的时候,如果元素的数目超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。

使用模式

在ArrayList和Vector中,从一个指定的位置(通过索引)查找数据或是在集合的末尾增加、移除一个元素所花费的时间是一样的,这个时间我们用O(1)表示。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线形增长:O(n-i),其中n代表集合中元素的个数,i代表元素增加或移除元素的索引位置。为什么会这样呢?以为在进行上述操作的时候集合中第i和第i个元素之后的所有元素都要执行位移的操作。这一切意味着什么呢?

这意味着,你只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是其他操作,你最好选择其他的集合操作类。比如,LinkList集合类在增加或移除集合中任何位置的元素所花费的时间都是一样的?O(1),但它在索引一个元素的使用缺比较慢-O(i),其中i是索引的位置.使用ArrayList也很容易,因为你可以简单的使用索引来代替创建iterator对象的操作。LinkList也会为每个插入的元素创建对象,所有你要明白它也会带来额外的开销。

最后,在《Practical Java》一书中Peter Haggar建议使用一个简单的数组(Array)来代替Vector或ArrayList。尤其是对于执行效率要求高的程序更应如此。因为使用数组(Array)避免了同步、额外的方法调用和不必要的重新分配空间的操作。

Vector和Hashtable都是jdk1.0的就有了的。后来到java2后,java的容器框架改动很多,为了兼容,就让Vector和Hashtable分别实现了新的容器框架的List和Map。ArrayList和HashMap都是java2(也就是jdk1.2)后才有的。

1. 安全、效率方面:如果要实现同步安全,则要用Vector和Hashtable,否则则用ArrayList和HashMap,因为ArrayList和HashMap不考虑同步安全的问题,所以效率要高些。但Collections类可以解决这个问题。

Collections.synchronizedList

Collections.synchronizedMap

2. 资源方面:当两者的容量已满时,它们都会自动增长其容量,但Vector是按其容量的一倍增长,而ArrayList则按其容量的50%增加,所以Vector更能节省资源。

3.迭代器:Vector和Hashtable使用Enumeration,ArrayList和HashMap使用Iterator

ARRAY是必须在声明的时候说明长度的; ARRYLIST也是和Vector类似,可以自动增加长度的。

List和Set的区别:

List用来处理序列,而Set用来处理集。

List中的内容可以重复,而Set则不行。

Vector,ArrayList和Hashtable,HashMap的区别:

1.Vector和ArrayList是数值联系对象。按照插入的顺序进行排列,可以有重复值。

2.Hashtable和HashMap是对象联系对象。按照自己的排列方式进行排序,不可以有重复值。

HashMap:继承了Map接口,实现用Keys来存储和访问Values,Keys和Values都可以为空,它与Hashtable类的区别在于Hashtable类的Keys不能为null,

Vector内部实际是以Array实现的,也通过元素的整数索引来访问元素,但它只能存放java.lang.Object对象,不能用于存放基本类型数据,比如要存放一个整数10,得用new Integer(10)构造出一个Integer包装类对象再放进去。

还有一点:

HASHMAP不是同步的,线程不安全的,HASHTABLE是同步的,线程安全的?

在Hashtable中,所有涉及到更新其中存放的内容的方法都是同步的

如:

public synchronized Object put(Object key, Object value) {}

public synchronized Object get(Object key) {}

...

以此来保证Hashtable不会被多个线程同时更改

因为HashMap的公共方法上没加synchronized关键字

如何理解synchronized 关键字呢?

比如:

用synchronized和不用synchronized简单的说就是

1个房子有2个门,用synchronized的是从有锁的门

进入房子,并且进入后锁门,出来后门打开。

而不用synchronized的是从没有锁的门进入。

从有锁的门进入的人只管把这个门锁上,但没办法干预从无锁的门进入的人。

所以如果clear()方法是synchronized,他进门后取走所有鸡蛋

这时如果一个非synchronized的get()方法想进门取得一个鸡蛋就出错了。

墨然殇

up 看完上面的应该知道够用了

BigDecimal怎么比较大小?

BigDecimal a = new BigDecimal("1.00");x0dx0aBigDecmial b = new BigDecimal(1);x0dx0a想比较一下a和b的大小,一般都会用equalsx0dx0aSystem.out.println(a.equals(b));x0dx0a但是输出结果是:falsex0dx0a原因是:BigDecimal比较时,不仅比较值,而且还比较精度?x0dx0aif(a.compareTo(b)==0) 结果是truex0dx0a比较大小可以用 a.compareTo(b) x0dx0a返回值 -1 小于 0 等于 1 大于
2023-06-27 19:07:311

BigDecimal对比大小使用compare而不使用equals

在bigdecimal的对比大小中,建议使用compare而不是使用equals。按理说0和0.00应该是相等,但在上图中发现返回结果却是false。equals源码: 可以发现当小数位scale不等时,自动返回了false。 compare源码: signnum源码: compare源码可见,先对小数位scale进行了对比,如果不等,又将两个数进行了转换,转成int,对比int的大小。
2023-06-27 19:07:401

bigdecimal比较大小

BigDecimal a = new BigDecimal (101.00); BigDecimal b = new BigDecimal (111.00); if(a.compareTo(b) == -1){ System.out.println("a小于b"); } if(a.compareTo(b) == 0){ System.out.println("a等于b"); } if(a.compareTo(b) == 1){ System.out.println("a大于b"); } if(a.compareTo(b) > -1){ System.out.println("a大于等于b"); } if(a.compareTo(b) < 1){ System.out.println("a小于等于b"); }
2023-06-27 19:07:491

BigDecimal使用详解

一、构造方法 BigDecimal的构造方法有很多种,大家最常用的如下方式: BigDecimal bd1=new BigDecimal(10); BigDecimal bd2=new BigDecimal("10"); 二、四则预算 加法:bigDecimal1.add(bigDecimal2); 减法:bigDecimal1.subtract(bigDecimal2); 乘法:bigDecimal1.multiply(bigDecimal2); 除法:bigDecimal1.divide(bigDecimal2); 三、对小数的处理 (1).DecimalFormat类 例: DecimalFormat df =new DecimalFormat("#.00"); df.format(3.1415926); 结果输出3.14 (2)setScale方法 double f = 111231.5585; BigDecimal b = new BigDecimal(f); double f1 = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); //保留2位小数 四、比较大小 BigDecimal比较大小不能使用equals因为不仅比较值还比较精度 这里使用BigDecimal自带方法compareTo 例: BigDecimal a = new BigDecimal("1.00"); BigDecmial b = new BigDecimal(1); a.compareTo(b)==0结果是true 这里返回值含义: -1小于 0等于 1大于
2023-06-27 19:07:571

java中不同类型数比大小的程序代码

int 、float等基本数据类型用==string 用eques
2023-06-27 19:08:073

bigdecimal可以用等号比较大小么

陆金所、人人贷还是比较靠谱的。
2023-06-27 19:08:202

在JAVA中怎么比较Double类型数据的大小

几乎所有数字类型的,同类型的,可以直接比较如 a , b 两个比较类似如下:if(a>b){}不同类型,一般按照大的那个类型来比较海枫科技
2023-06-27 19:08:291

39的40次方与40的39次方大小是什么?

import java.math.BigDecimal;public class Case5 {public static void main(String[] args) {test1();}public static void test1() {BigDecimal base39 = new BigDecimal(39);BigDecimal base40 = new BigDecimal(40);base39 = base39.pow(40);base40 = base40.pow(39);System.out.println("39的40次方="+base39);System.out.println("40的39次方="+base40);String result = base39.compareTo(base40)>0? "39的40次方 比 40的39次方大" : "40的39次方 比 39的40次方大";System.out.println(result);}}39的40次方=439121075102077650905178851056667333727749210354866416338812640140的39次方=30223145490365729367654400000000000000000000000000000000000000039的40次方 比 40的39次方大任何非零数的0次方都等于1。原因如下通常代表3次方5的3次方是125,即5×5×5=1255的2次方是25,即5×5=255的1次方是5,即5×1=5由此可见,n≧0时,将5的(n+1)次方变为5的n次方需除以一个5,所以可定义5的0次方为:5 ÷ 5 = 1
2023-06-27 19:08:541

怎么将parsefloat转换的数比较大小

js的Number精度明显达不到你的要求,不能实现 。 你应该考虑一下为什么需要转换成数字?实在没有其他途径的时候可以采用bigdecimal的工具库
2023-06-27 19:09:021

Java泛型Number能比较大小吗?

理论上可以这样实现,不过我还没有测试private static int compare(Number v1 , Number v2){BigDecimal v11 = new BigDecimal(v1.toString());BigDecimal v22 = new BigDecimal(v2.toString());return v11.compareTo(v22);}
2023-06-27 19:09:267

Java中Double的比较?

double a = 0.001; double b = 0.0011; BigDecimal data1 = new BigDecimal(a); BigDecimal data2 = new BigDecimal(b); data1.compareTo(data2) 非整型数,运算由于精度问题,可能会有误差,建议使用BigDecimal类型!
2023-06-27 19:10:052

0

1. publicclassIntegerTypeTest01{2. publicstaticvoidmain(
2023-06-27 19:10:562

java练习:自定义一个求最大值的类?

根据规则,重载是根据传入的参数不同而出现的类似于只能判断吧在这里先解决一下重载的问题,你可以试着用数据类型int和double去重载方法就是不同类型的数和不同类型的数去做比较下一步在方法中把三个数字放在数组中然后使用排序算法或者数组本身的那个排序函数,这里有冒泡排序和其他方式然后把最大值返回出去,或者在重载方法最后敲一句打印这X,Y,Z三个值中最大值是:?的话。有帮助别忘记采纳亲!
2023-06-27 19:11:073

编写一个JAVA计算器程序

你会被鄙视的 又到一年答辩论文时 不会你就拿这东西当论文吧!???
2023-06-27 19:11:466

java中有类似支持C语言的MIRACL大数运算库吗,可以实现模幂运算的,大数加减乘除之类的

参考jdk中的BigInteger和BigDecinal类,它们定义了你所需要的大数运算
2023-06-27 19:12:061

java 中 BigDecimal 怎么与 0 比较

把0转成BigDecimal不就可以比了吗
2023-06-27 19:12:285

编写一个java程序,任意输入三个数,能按大小排列出?

int[] a = { 5, 4, 2, 4, 9, 1 }; Arrays.sort(a); // 进行排序 for (int i : a) { System.out.print(i); }
2023-06-27 19:12:462

(Java)设计一个算法,计算出n阶乘中尾部零的个数

负数?x最小值都只能取到0啊
2023-06-27 19:13:042

java 中BigDecimal类型的数据和int类型的常量怎么比较??

下面是我刚刚写的1和1比较的代码,自己观察一下就会了import java.math.BigDecimal;public class Main { public static void main(String args[]){ BigDecimal a; a = BigDecimal.ONE; System.out.println(a.compareTo(BigDecimal.valueOf(1))); }}
2023-06-27 19:13:231

java中如何对较大的数字进行计算

不管是不是用JAVA,其实方法都一样,利用数组比如说长度为一千的数字,可以这个 int[] number = new int[1000];相加的思路是,首先两个数组的长度必须是一致,位数不同的话,前面补0,内存有点浪费,但是计算起来比较方便。然后让它们从0到最高位,每位进行相加并保存相应的位置上。最后一步是从0开始判断有没有大于10的数字,如果有就向前面进位(前一个加1,当前位减10),这样就可以。如果是相减,其实思路还是一样的,每位先相减,再判断是否有小于0的,如果有则向前面一位借1(前一位减1,当前位加10)如果是相乘,和上面一样,不过要注意的是进位的时候,不止进一位,比如5*6,就要向前进3位了(前一位加3,当前位减30)除就比较麻烦点,要涉及到精确度问题,得看实际需要 输出就更容易了,直接for循环数组 特别要注意的是,如果最高位有进位的时候,这个是比较容易出错的地方 思路在上面,如果实现不了请留言
2023-06-27 19:13:341

delphi 窗体右键弹出“打印”要直接横向打印,不要跳出打印设置怎么弄,解释详细点,我是初学者

我晕,你直接在我上次的回答上追问就行拉,这些放在按钮的事件里面,比如说:procedure Tmainform.printButtonClick(Sender: TObject);begini := Printer.Printers.IndexOf("printer name"); // 代入打印机名字if i >= 0 then Printer.PrinterIndex := i; // 设定打印机Printer.Orientation := poLandscape; //设定横向打印Printer.BeginDoc; // 设定打印内容 // Set up a large blue font Canvas.Font.Size := 20; Canvas.Font.Color := clBlue; // Write out the page size Canvas.TextOut(20, 20, "Page width = "+IntToStr(PageWidth)); // Finish printingPrinter.EndDoc;end;
2023-06-27 19:13:431

浮点小数的表示方法

Java 语言支持两种基本的浮点类型: float 和 double ,以及与它们对应的包装类 Float 和 Double 。它们都依据 IEEE 754 标准,该标准为 32 位浮点和 64 位双精度浮点二进制小数定义了二进制标准。 IEEE 754 用科学记数法以底数为 2 的小数来表示浮点数。IEEE 浮点数用 1 位表示数字的符号,用 8 位来表示指数,用 23 位来表示尾数,即小数部分。作为有符号整数的指数可以有正负之分。小数部分用二进制(底数 2)小数来表示,这意味着最高位对应着值 ?(2 -1),第二位对应着 ?(2 -2),依此类推。对于双精度浮点数,用 11 位表示指数,52 位表示尾数。IEEE 浮点值的格式如图 1 所示。 图 1. IEEE 754 浮点数的格式 因为用科学记数法可以有多种方式来表示给定数字,所以要规范化浮点数,以便用底数为 2 并且小数点左边为 1 的小数来表示,按照需要调节指数就可以得到所需的数字。所以,例如,数 1.25 可以表示为尾数为 1.01,指数为 0: (-1) 0*1.01 2*2 0 数 10.0 可以表示为尾数为 1.01,指数为 3: (-1) 0*1.01 2*2 3 特殊数字除了编码所允许的值的标准范围(对于 float ,从 1.4e-45 到 3.4028235e+38),还有一些表示无穷大、负无穷大、 -0 和 NaN(它代表“不是一个数字”)的特殊值。这些值的存在是为了在出现错误条件(譬如算术溢出,给负数开平方根,除以 0 等)下,可以用浮点值集合中的数字来表示所产生的结果。 这些特殊的数字有一些不寻常的特征。例如, 0 和 -0 是不同值,但在比较它们是否相等时,被认为是相等的。用一个非零数去除以无穷大的数,结果等于 0 。特殊数字 NaN 是无序的;使用 == 、 < 和 > 运算符将 NaN 与其它浮点值比较时,结果为 false 。如果 f 为 NaN,则即使 (f == f) 也会得到 false 。如果想将浮点值与 NaN 进行比较,则使用 Float.isNaN() 方法。表 1 显示了无穷大和 NaN 的一些属性。 表 1. 特殊浮点值的属性表达式 结果 Math.sqrt(-1.0) -> NaN 0.0 / 0.0 -> NaN 1.0 / 0.0 -> 无穷大 -1.0 / 0.0 -> 负无穷大 NaN + 1.0 -> NaN 无穷大 + 1.0 -> 无穷大 无穷大 + 无穷大 -> 无穷大 NaN > 1.0 -> false NaN == 1.0 -> false NaN < 1.0 -> false NaN == NaN -> false 0.0 == -0.01 -> true 基本浮点类型和包装类浮点有不同的比较行为使事情更糟的是,在基本 float 类型和包装类 Float 之间,用于比较 NaN 和 -0 的规则是不同的。对于 float 值,比较两个 NaN 值是否相等将会得到 false ,而使用 Float.equals() 来比较两个 NaN Float 对象会得到 true 。造成这种现象的原因是,如果不这样的话,就不可能将 NaN Float 对象用作 HashMap 中的键。类似的,虽然 0 和 -0 在表示为浮点值时,被认为是相等的,但使用 Float.compareTo() 来比较作为 Float 对象的 0 和 -0 时,会显示 -0 小于 0 。 浮点中的危险由于无穷大、NaN 和 0 的特殊行为,当应用浮点数时,可能看似无害的转换和优化实际上是不正确的。例如,虽然好象 0.0-f 很明显等于 -f ,但当 f 为 0 时,这是不正确的。还有其它类似的 gotcha,表 2 显示了其中一些 gotcha。 表 2. 无效的浮点假定这个表达式…… 不一定等于…… 当…… 0.0 - f -f f 为 0 f < g ! (f >= g) f 或 g 为 NaN f == f true f 为 NaN f + g - g f g 为无穷大或 NaN 舍入误差浮点运算很少是精确的。虽然一些数字(譬如 0.5 )可以精确地表示为二进制(底数 2)小数(因为 0.5 等于 2 -1),但其它一些数字(譬如 0.1 )就不能精确的表示。因此,浮点运算可能导致舍入误差,产生的结果接近 ― 但不等于 ― 您可能希望的结果。例如,下面这个简单的计算将得到 2.600000000000001 ,而不是 2.6 : double s=0; for (int i=0; i<26; i++) s += 0.1; System.out.println(s);类似的, .1*26 相乘所产生的结果不等于 .1 自身加 26 次所得到的结果。当将浮点数强制转换成整数时,产生的舍入误差甚至更严重,因为强制转换成整数类型会舍弃非整数部分,甚至对于那些“看上去似乎”应该得到整数值的计算,也存在此类问题。例如,下面这些语句: double d = 29.0 * 0.01; System.out.println(d); System.out.println((int) (d * 100));将得到以下输出:0.29 28这可能不是您起初所期望的。浮点数比较指南由于存在 NaN 的不寻常比较行为和在几乎所有浮点计算中都不可避免地会出现舍入误差,解释浮点值的比较运算符的结果比较麻烦。最好完全避免使用浮点数比较。当然,这并不总是可能的,但您应该意识到要限制浮点数比较。如果必须比较浮点数来看它们是否相等,则应该将它们差的绝对值同一些预先选定的小正数进行比较,这样您所做的就是测试它们是否“足够接近”。(如果不知道基本的计算范围,可以使用测试“abs(a/b - 1) < epsilon”,这种方法比简单地比较两者之差要更准确)。甚至测试看一个值是比零大还是比零小也存在危险 ―“以为”会生成比零略大值的计算事实上可能由于积累的舍入误差会生成略微比零小的数字。NaN 的无序性质使得在比较浮点数时更容易发生错误。当比较浮点数时,围绕无穷大和 NaN 问题,一种避免 gotcha 的经验法则是显式地测试值的有效性,而不是试图排除无效值。在清单 1 中,有两个可能的用于特性的 setter 的实现,该特性只能接受非负数值。第一个实现会接受 NaN,第二个不会。第二种形式比较好,因为它显式地检测了您认为有效的值的范围。清单 1. 需要非负浮点值的较好办法和较差办法 // Trying to test by exclusion -- this doesn"t catch NaN or infinity public void setFoo(float foo) { if (foo < 0) throw new IllegalArgumentException(Float.toString(f)); this.foo = foo; } // Testing by inclusion -- this does catch NaN public void setFoo(float foo) { if (foo >= 0 && foo < Float.INFINITY) this.foo = foo; else throw new IllegalArgumentException(Float.toString(f)); }不要用浮点值表示精确值一些非整数值(如几美元和几美分这样的小数)需要很精确。浮点数不是精确值,所以使用它们会导致舍入误差。因此,使用浮点数来试图表示象货币量这样的精确数量不是一个好的想法。使用浮点数来进行美元和美分计算会得到灾难性的后果。浮点数最好用来表示象测量值这类数值,这类值从一开始就不怎么精确。用于较小数的 BigDecimal从 JDK 1.3 起,Java 开发人员就有了另一种数值表示法来表示非整数: BigDecimal 。 BigDecimal 是标准的类,在编译器中不需要特殊支持,它可以表示任意精度的小数,并对它们进行计算。在内部,可以用任意精度任何范围的值和一个换算因子来表示 BigDecimal ,换算因子表示左移小数点多少位,从而得到所期望范围内的值。因此,用 BigDecimal 表示的数的形式为 unscaledValue*10 -scale 。 用于加、减、乘和除的方法给 BigDecimal 值提供了算术运算。由于 BigDecimal 对象是不可变的,这些方法中的每一个都会产生新的 BigDecimal 对象。因此,因为创建对象的开销, BigDecimal 不适合于大量的数学计算,但设计它的目的是用来精确地表示小数。如果您正在寻找一种能精确表示如货币量这样的数值,则 BigDecimal 可以很好地胜任该任务。 所有的 equals 方法都不能真正测试相等如浮点类型一样, BigDecimal 也有一些令人奇怪的行为。尤其在使用 equals() 方法来检测数值之间是否相等时要小心。 equals() 方法认为,两个表示同一个数但换算值不同(例如, 100.00 和 100.000 )的 BigDecimal 值是不相等的。然而, compareTo() 方法会认为这两个数是相等的,所以在从数值上比较两个 BigDecimal 值时,应该使用 compareTo() 而不是 equals() 。 另外还有一些情形,任意精度的小数运算仍不能表示精确结果。例如, 1 除以 9 会产生无限循环的小数 .111111... 。出于这个原因,在进行除法运算时, BigDecimal 可以让您显式地控制舍入。 movePointLeft() 方法支持 10 的幂次方的精确除法。 使用 BigDecimal 作为互换类型SQL-92 包括 DECIMAL 数据类型,它是用于表示定点小数的精确数字类型,它可以对小数进行基本的算术运算。一些 SQL 语言喜欢称此类型为 NUMERIC 类型,其它一些 SQL 语言则引入了 MONEY 数据类型,MONEY 数据类型被定义为小数点右侧带有两位的小数。 如果希望将数字存储到数据库中的 DECIMAL 字段,或从 DECIMAL 字段检索值,则如何确保精确地转换该数字?您可能不希望使用由 JDBC PreparedStatement 和 ResultSet 类所提供的 setFloat() 和 getFloat() 方法,因为浮点数与小数之间的转换可能会丧失精确性。相反,请使用 PreparedStatement 和 ResultSet 的 setBigDecimal() 及 getBigDecimal() 方法。 对于 BigDecimal ,有几个可用的构造函数。其中一个构造函数以双精度浮点数作为输入,另一个以整数和换算因子作为输入,还有一个以小数的 String 表示作为输入。要小心使用 BigDecimal(double) 构造函数,因为如果不了解它,会在计算过程中产生舍入误差。请使用基于整数或 String 的构造函数。 构造 BigDecimal 数对于 BigDecimal ,有几个可用的构造函数。其中一个构造函数以双精度浮点数作为输入,另一个以整数和换算因子作为输入,还有一个以小数的 String 表示作为输入。要小心使用 BigDecimal(double) 构造函数,因为如果不了解它,会在计算过程中产生舍入误差。请使用基于整数或 String 的构造函数。 如果使用 BigDecimal(double) 构造函数不恰当,在传递给 JDBC setBigDecimal() 方法时,会造成似乎很奇怪的 JDBC 驱动程序中的异常。例如,考虑以下 JDBC 代码,该代码希望将数字 0.01 存储到小数字段: PreparedStatement ps = connection.prepareStatement("INSERT INTO Foo SET name=?, value=?"); ps.setString(1, "penny"); ps.setBigDecimal(2, new BigDecimal(0.01)); ps.executeUpdate();在执行这段似乎无害的代码时会抛出一些令人迷惑不解的异常(这取决于具体的 JDBC 驱动程序),因为 0.01 的双精度近似值会导致大的换算值,这可能会使 JDBC 驱动程序或数据库感到迷惑。JDBC 驱动程序会产生异常,但可能不会说明代码实际上错在哪里,除非意识到二进制浮点数的局限性。相反,使用 BigDecimal("0.01") 或 BigDecimal(1, 2) 构造 BigDecimal 来避免这类问题,因为这两种方法都可以精确地表示小数。
2023-06-27 19:13:501

java中如何实现字符与数字加减运算

JAVA中一样也的 会进行由低到高自动转换public class TestTranform { public static void main(String[] args) { char b="c"; int a=4; int d= a+b; System.out.println (d); }}
2023-06-27 19:13:593

double money = 2; BigDecimal money2 = new BigDecimal("2"); 这2个声明对象有什么区别 1个带new一个不带

在java中提供了大数字的操作类,即java.math.BinInteger类和java.math.BigDecimal类。这两个类用于高精度计 算,其中BigInteger类是针对大整数的处理类,而BigDecimal类则是针对大小数的处理类。下边我们介绍BigDecimal类: BigDecimal的实现利用到了BigInteger,不同的是BigDecimal加入了小数的概念。一般的float型和Double型数据只可 以用来做科学计算或者是工程计算,由于在商业计算中,要求的数字精度比较高,所以要用到java.math.BigDecimal类,它支持任何精度的定 点数,可以用它来精确计算货币值。Double(双精度浮点型)是计算机使用的一种资料型别。比起单精度浮点数(float),Double(双精度浮点数)使用 64 位(8字节) 来储存一个浮点数。 它可以表示十进制的15或16位有效数字,负值取值范围为 -1.79769313486231570E+308 到 -4.94065645841246544E-324,正值取值范围为 4.94065645841246544E-324 到 1.79769313486231570E+308
2023-06-27 19:14:061

java中什么是严格的浮点计算?请解释下,谢谢。

所有的小数都要保留。一般用BigDecimal比较好
2023-06-27 19:14:143

java中怎么判断一个double类型的数等于零。

double? 直接 a ==0 判断
2023-06-27 19:14:343

java.math.BigDecimal cannot be cast to java.lang.Integer说类型不能转换,求解释!

Integer不是基本类型,是int的包装类,无法把包装当做基本类型来用。比如,char a = "c"; int b = (Integer)a; 这样也是回报cannot cast错误的。必须是(int)a,用基本类型才能转。这是第一个问题。第二个问题 你的list.get(i).get("goods_amout")得到的应该是BigDecimal类型的,这个类型,不能用基本类型强转的。举个简单的例子,string a = "c"; int b = (int)a; 可以这样吗? 要转化这个,用intValue(),也就是:list.get(i).get("goods_amout").intValue() 这样得到的就是个int 的值了。
2023-06-27 19:15:074

java 判断一个数值是否在一个数值区间内

if((x>100)&&(x<=200)){ system.out.println("在a区间");}else if((x>200)&&(x<=300))){ system.out.println("在b区间");}else if((x>300)&&(x<=400))){ system.out.println("在c区间");}else{ system.out.println("不符合区间");}
2023-06-27 19:15:232

上海久雅Java面试题

题目在哪里呢???
2023-06-27 19:15:432

BigDecimal怎么比大小?

BigDecimal比大小,需要声明两个BigDecimal类型变量b1和b2,调用equals()方法比较大小。BigDecimal a = new BigDecimal("1.00");BigDecmial b = new BigDecimal(1);想比较一下a和b的大小,一般都会用equals。BigDecimal其他情况简介。使用BigDecimal类构造方法传入double类型时,计算的结果也是不精确的。因为不是所有的浮点数都能够被精确的表示成一个double 类型值,有些浮点数值不能够被精确的表示成 double 类型值,因此它会被表示成与它最接近的 double 类型的值。必须改用传入String的构造方法。这一点在BigDecimal类的构造方法注释中有说明。BigDecimal向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同。
2023-06-27 19:16:031

BigDecimal比较大小怎么算的?

BigDecimal比大小,需要声明两个BigDecimal类型变量b1和b2,调用equals()方法比较大小。BigDecimal a = new BigDecimal("1.00");BigDecmial b = new BigDecimal(1);想比较一下a和b的大小,一般都会用equals。BigDecimal其他情况简介。使用BigDecimal类构造方法传入double类型时,计算的结果也是不精确的。因为不是所有的浮点数都能够被精确的表示成一个double 类型值,有些浮点数值不能够被精确的表示成 double 类型值,因此它会被表示成与它最接近的 double 类型的值。必须改用传入String的构造方法。这一点在BigDecimal类的构造方法注释中有说明。BigDecimal向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同。
2023-06-27 19:16:181

BigDecimal 怎么比较大小

当然是使用compareTo:new BigDecimal(1).compareTo(new BigDecimal("1.0"))但是,注意:compareTo 其实也有坑。如果试用:new BigDecimal(1) 与new BigDecimal("1.00"),结果是true. 但是换成 new BigDecimal(1.2).compareTo(new BigDecimal("1.20")),结果就是false.这时问题又来了。所以保险的办法是把小数位去掉再比较。比如*100。都升到个位数。或者统一使用setScale定好小数位。我之前就不知这个坑,搞了好久。
2023-06-27 19:17:444

bigdeal和big integer比较大小怎么比较?

BigDecimal比大小,需要声明两个BigDecimal类型变量b1和b2,调用equals()方法比较大小。BigDecimal a = new BigDecimal("1.00");BigDecmial b = new BigDecimal(1);想比较一下a和b的大小,一般都会用equals。BigDecimal其他情况简介。使用BigDecimal类构造方法传入double类型时,计算的结果也是不精确的。因为不是所有的浮点数都能够被精确的表示成一个double 类型值,有些浮点数值不能够被精确的表示成 double 类型值,因此它会被表示成与它最接近的 double 类型的值。必须改用传入String的构造方法。这一点在BigDecimal类的构造方法注释中有说明。BigDecimal向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同。
2023-06-27 19:18:171

BigDecimal怎么比较大小?

BigDecimal a = new BigDecimal("1.00");BigDecmial b = new BigDecimal(1);想比较一下a和b的大小,一般都会用equalsSystem.out.println(a.equals(b));但是输出结果是:false原因是:BigDecimal比较时,不仅比较值,而且还比较精度?if(a.compareTo(b)==0) 结果是true比较大小可以用 a.compareTo(b) 返回值 -1 小于 0 等于 1 大于
2023-06-27 19:18:321

c语言中double类型值的大小比较

可以这么比较啊,不会有什么异常,把上下代码贴上来看看
2023-06-27 19:19:0011

java中BigDecimal怎么与0比较?

标准做法int r=big_decimal.compareTo(BigDecimal.Zero); //和0,Zero比较if(r==0) //等于if(r==1) //大于if(r==-1) //小于或者if(big_decimal.equals(BigDecimal.Zero)) //是否等于0
2023-06-27 19:19:331

java中BigDecimal怎么与0比较?

标准做法x0dx0aintr=big_decimal.compareTo(BigDecimal.Zero);//和0,Zero比较x0dx0aif(r==0)//等于x0dx0aif(r==1)//大于x0dx0aif(r==-1)//小于x0dx0ax0dx0a或者x0dx0aif(big_decimal.equals(BigDecimal.Zero))//是否等于0
2023-06-27 19:20:311

分析一句英文的结构。

倒装句。economies是宾语,war是主语。正常的语序是the war had destroyed the Europeans" and Asians" economies. 作从句的时候,先将the Europeans" and Asians" economies提前,成为倒装句the Europeans" and Asians" economies the war had destroyed. 然后用引导词whose替换the Europeans" and Asians"。这种语序可以表示强调。就如同:Him she has deceived.
2023-06-27 19:11:201

buy的过去式是什么

buy的过去式是bought.
2023-06-27 19:11:303

中国人表达情感的方式 英文

上面那个作文 都是语法错误 要是炒上去了,必死无疑。像是用翻译器翻译出来的。我建议你去必应 或是 谷歌上面去搜搜看吧。
2023-06-27 19:11:3110

buy的过去式是什么

buy的过去式是bought.词汇分析单词:buy音标:英[bau026a]美[bau026a]释义:vt. 购买,购得;n. 交易,买卖; 便宜货;vt. 够支付; 买通; 收买; 贿赂;短语Best buy 百思买 ; 百思买集团 ; 百思买公司 ; 百思卖buy order 买盘 ; 买方指令 ; 买入委托 ; 买单委托buy back 购回 ; 回购 ; 买回 ; 产品返销special buy 大贱卖 ; 大 ; 大甩卖Conviction Buy 强力买入 ; 确信买入 ; 强烈推荐买入 ; 强势买入Buy China 购买中国货 ; 买中国货 ; 购买国 ; 买国货例句1、Did you make this shirt or buy it?这件衬衣是你自己做的还是买的?2、She asked from her mother enough money to buy the skirt.她向她母亲要了足够的钱来买这条裙子。3、I wonder at your allowing her to buy the expensive clothes.我对你答应她买这么贵的衣服感到吃惊。4、We are queuing up to buy tickets for the concert.我们正在排队等候买音乐会的入场券。5、He is saving up to buy a home for his family.他在储蓄以便买一幢住宅供全家居住。
2023-06-27 19:11:372

buy的过去式是什么

buy的过去式是bought,具体释义如下:读音:[bu0254u02d0t]表达意思:买(buy的过去式和过去分词);从商店购买的。词性:通常在句中既可以作形容词,也可以作动词。固定搭配:bought and sold note买卖单据;证券经纪人。buy的用法1、buy sth at+商店(在某商店买某物)He bought a table at that store.他在那个商店买了一张桌子。2、buy sb. sth(给某人买某物)My husband bought me a new coat.我丈夫给我买了一件新外套。3、buy sth for sb.(为某人买某物)但不能这样搭配:buy sth to sb.Her mother bought a new book for her.她妈妈给她买了一本新书。buy的用法
2023-06-27 19:11:442

这段的完整句子结构分析怎么分

There is a difference between American and European customs( in using the knife and fork). Europeans keep the knife (in the right hand), the fork (in the left). They use both hands( in eating). Americans, (on the contrary), use just one hand whenever possible and keep the other one on their lap. They constantly change their fork to the left hand【 when they have to cut meat】. (Between bites) they put the fork on their plate【 while drinking coffee or buttering bread】. Europeans are more apt to drink coffee (after the meal) and to keep their knife and fork in hand until they finish eating.
2023-06-27 19:11:562

buy的过去式

buy的过去式是bought,过去分词是bought,buy作为动词时购买,获得的意思。buy在句子中一般是用作及物动词,后面一般接名词或者代名词,有些时候还可以接双宾语。buy的主语一般都是人,不是没有生命的事物。如果用作”在商店购买“的意思,就可以加介词at,如果用作“从某处购买”的意思,就可以加介词from, of, off等,如果用作“给某人买”的意思,就可以说buy sb sth,不可以说buy sth to sb。
2023-06-27 19:12:002

buy的过去式

buy的过去式是bought,具体释义如下:读音:[bu0254u02d0t]表达意思:买(buy的过去式和过去分词);从商店购买的。词性:通常在句中既可以作形容词,也可以作动词。固定搭配:bought and sold note买卖单据;证券经纪人。buy的用法1、buy sth at+商店(在某商店买某物)He bought a table at that store.他在那个商店买了一张桌子。2、buy sb. sth(给某人买某物)My husband bought me a new coat.我丈夫给我买了一件新外套。3、buy sth for sb.(为某人买某物)但不能这样搭配:buy sth to sb.Her mother bought a new book for her.她妈妈给她买了一本新书。buy的用法
2023-06-27 19:11:152

求几篇介绍欧洲国家风土人情的英文作文,谁的好,选谁的!

Europe”—the word calls to mind a land of famous old buildings, scenic countryside, and time-honored traditions. Europe is rich in history. Ancient stone castles, lavish palaces, and beautiful cathedrals dot the land. But it"s also one of the world"s most vibrant, modern places. Europe attracts visitors from around the world. They come to see its historic landmarks, world-class art museums, and great natural beauty. Scenic attractions include the rolling green hills of the British Isles, towering peaks of the Swiss Alps, and sunny Mediterranean beaches. PENINSULAS AND ISLANDS Europe is considered a separate continent. But it"s actually a peninsula—a piece of land that juts out from a mainland into water. Europe is a giant peninsula sticking west out of Asia, the mainland. The Ural Mountains east of Europe divide the continent from Asia. The mountains run right through Russia. Russia lies partly in Europe and partly in Asia. Europe has many smaller peninsulas of its own. Greece and Italy are peninsulas. Spain and Portugal share another peninsula called Iberia. In the north, Denmark occupies the small peninsula of Jutland. Sweden and Norway occupy the larger Scandinavian Peninsula. Europe also includes many islands, such as Great Britain, Ireland, Sardinia, Corsica, Sicily, and Crete. All of these islands and peninsulas give Europe a long coastline and many harbors, inlets, and seaports. A CROWDED CONTINENT Europe is the second smallest of the world"s seven continents. Only Australia is smaller. Europe is about the same size as the United States. Yet it has almost three times as many people. About 729 million people live in Europe. That makes it the most crowded of all the continents. Europe is divided into more than 40 countries, and Europeans speak more than 60 languages. Europe is home to dozens of great cities. Many of them, such as London and Paris, date to ancient times. Among Europe"s other famous cities are A
2023-06-27 19:11:101

buy的过去式是什么

buy的过去式是bought。buy的过去式是bought作为动词表示买的意思,作为形容词表示从商店购买的意思。相关例句:I bought a one-way ticket to England today我今天买了张去英国的单程票。She bought a ton of clothes at the store她在店里买了一堆衣服。
2023-06-27 19:11:051

这句英语的语法成分能给分析一下吗?顺便翻译一下

美国和美国的梦想是国富民强,欧洲人和亚洲人在战争毁掉了他们的经济,
2023-06-27 19:10:555

欧美怎么说,英语?

western
2023-06-27 19:10:395

向高手求助几道GRE填空题

我先回答第一题,两空题先看第二空,因为总体上根据重复原则,所以和stranger对应,其次看第一空,even though那句是考虑 they 和stanger 的关系,当我们把“foreignness”带入第二空之后,主句的意思就表明:Europeans 把foreignness 和danger联系起来了,言外之意就是认为foreigness 是危险地,而主句又有not 取反,所以even though是那种不友好的感觉所以选择那个答案
2023-06-27 19:10:192