一:首谈java中的包装类
?????Java为基本类型提供包装类,这使得任何接受对象的操作也可以用来操作基本类型,直接将简单类型的变量表示为一个类,在执行变量类型的相互转换时,我们会大量使用这些包装类。java是一种面向对象语言,java中的类把方法与数据连接在一起,并构成了自包含式的处理单元.但在java中不能定义基本类型(primitive?type),为了能将基本类型视为对象来处理,并能连接相关的方法,java为每个基本类型都提供了包装类,这样,我们便可以把这些基本类型转化为对象来处理了.这些包装类有:Boolean,Byte,Short,Character,Integer,Long,Float,Void等
值得说明的是,java是可以直接处理基本类型的,但是在有些情况下我们需要将其作为对象来处理,这时就需要将其转化为包装类了.所有的包装类(Wrapper?Class)都有共同的方法,他们是:
(1)带有基本值参数并创建包装类对象的构造函数.如可以利用Integer包???装类创建对象,Integer?obj=new?Integer(145);
(2)带有字符串参数并创建包装类对象的构造函数.如new?Integer("-45.36");
(3)生成字符串表示法的toString()方法,如obj.toString().
(4)对同一个类的两个对象进行比较的equals()方法,如obj1.eauqls(obj2);
(5)生成哈稀表代码的hashCode方法,如obj.hasCode();
(6)将字符串转换为基本值的?parseType方法,如Integer.parseInt(args[0]);
(7)可生成对象基本值的typeValue方法,如obj.intValue();
在一定的场合,运用java包装类来解决问题,能大大提高编程效率.
包装类的自动装箱,自动拆箱
所谓装箱,就是把基本类型用它们相对应的引用类型包起来,使它们可以具有对象的特质,如我们可以把int型包装成Integer类的对象,或者把double包装成Double,等等。?
所谓拆箱,就是跟装箱的方向相反,将Integer及Double这样的引用类型的对象重新简化为值类型的数据?
javaSE5.0后提供了自动装箱与拆箱的功能,此功能事实上是编译器来帮您的忙,编译器在编译时期依您所编写的方法,决定是否进行装箱或拆箱动作。?
自动装箱的过程:每当需要一种类型的对象时,这种基本类型就自动地封装到与它相同类型的包装中。?
自动拆箱的过程:每当需要一个值时,被装箱对象中的值就被自动地提取出来,没必要再去调用intValue()和doubleValue()方法。?
自动装箱,只需将该值赋给一个类型包装器引用,java会自动创建一个对象。例如:Integer?i=100;//没有通过使用new来显示建立,java自动完成。?
自动拆箱,只需将该对象值赋给一个基本类型即可,例如
·?int?i?=?11;??
·?Integer?j?=?i;?//自动装箱??
·?int?k?=?j?//自动拆箱?
然而在Integer的自动装拆箱会有些细节值得注意:
public?static?void?main(String[]?args)?{??
????Integer?a=100;??
????Integer?b=100;???
????Integer?c=200;??
????Integer?d=200;???
???System.out.println(a==b);???//1??
???System.out.println(a==100);?//2?????
??System.out.println(c==d);???//3??
??System.out.println(c==200);?//4??
???}??
在java种,"=="是比较object的reference而不是value,自动装箱后,abcd都是Integer这个Oject,因此“==”比较的是其引用。按照常规思维,1和3都应该输出false。但结果是:?
true?
true?
false?
true
结果2和4,是因为ac进行了自动拆箱,因此其比较是基本数据类型的比较,就跟int比较时一样的,“==”在这里比较的是它们的值,而不是引用。?
对于结果1,虽然比较的时候,还是比较对象的reference,但是自动装箱时,java在编译的时候?Integer?a?=?100;?被翻译成->?Integer?a?=?Integer.valueOf(100);?
关键就在于这个valueOf()的方法。?
public?static?Integer?valueOf(int?i)?{?????
final?int?offset?=?128;?????
if?(i?>=?-128?&&?i?<=?127)?{?//?must?cache?????
return?IntegerCache.cache[i?+?offset];?????
}?????
return?new?Integer(i);?????
}?????
private?static?class?IntegerCache?{?????
private?IntegerCache(){}?????
static?final?Integer?cache[]?=?new?Integer[-(-128)?+?127?+?1];?????
static?{?????
for(int?i?=?0;?i?<?cache.length;?i++)?????
cache?=?new?Integer(i?-?128);?????
}?????
}???
根据上面的jdk源码,java为了提高效率,IntegerCache类中有一个数组缓存?了值从-128到127的Integer对象。当我们调用Integer.valueOf(int?i)的时候,如果i的值是>=-128且<=127时,会直接从这个缓存中返回一个对象,否则就new一个Integer对象。?
具体如下:?
static?final?Integer?cache[]?=?new?Integer[-(-128)?+?127?+?1];?//将cache[]变成静态??
static?{??
????????for(int?i?=?0;?i?<?cache.length;?i++)??
????????cache[i]?=?new?Integer(i?-?128);?//初始化cache[i]??
}??
这是用一个for循环对数组cache赋值,cache[255]?=?new?Integer(255-128),也就是newl一个Integer(127)?,并把引用赋值给cache[255],好了,然后是Integer?b=?127,流程基本一样,最后又到了cache[255]?=?new?Integer(255-128),这一句,那我们迷糊了,这不是又new了一个对象127吗,然后把引用赋值给cache[255],我们比较这两个引?用(前面声明a的时候也有一个),由于是不同的地址,所以肯定不会相等,应该返回false啊!呵呵,这么想你就错了,请注意看for语句给?cache[i]初始化的时候外面还一个{}呢,{}前面一个大大的static关键字,是静态的,那么我们就可以回想下static有什么特性了,只能?初始化一次,在对象间共享,也就是不同的对象共享同一个static数据
。那么当我们Integer?b?=?127的时候,并没有new出一个新对象来,而是共享了a这个对象的引用,记住,他们共享了同一个引用!!!,那么我们进行比较a==b时,由于是同一个对象的引用(她们在堆中的地址相同),那当然返回true了!!!?
二:进军集合类
集合其实就是存放对象的容器,专业点说就是集合是用来存储和管理其他对象的对象,即对象的容器。集合可以扩容,长度可变,可以存储多种类型的数据,而数组长度不可变,只能存储单一类型的元素
用一张图来总结一下集合的总况:
下面是网上找的一个图片:
集合中的结构和几个实现类:
总述:List、Set、Map是这个集合体系中最主要的三个接口。
其中List和Set继承自Collection接口。
Set不允许元素重复。HashSet和TreeSet是两个主要的实现类。
List有序且允许元素重复。ArrayList、LinkedList和Vector是三个主要的实现类。
???Map也属于集合系统,但和Collection接口不同。Map是key对value的映射集合,其中key列就是一个集合。key不能重复,但是value可以重复。HashMap、TreeMap和Hashtable是三个主要的实现类。
???SortedSet和SortedMap接口对元素按指定规则排序,SortedMap是对key列进行排序。
具体来说:
1.Collection?接口用于表示任何对象或元素组。想要尽可能以常规方式处理一组元素时,就使用这一接口。
操作:
(1)?单元素添加、caozuo.html" target="_blank">删除操作:
boolean?add(Object?o):将对象添加给集合
boolean?remove(Object?o):?如果集合中有与o相匹配的对象,则删除对象o
(2)?查询操作:
int?size()?:返回当前集合中元素的数量
boolean?isEmpty()?:判断集合中是否有任何元素
boolean?contains(Object?o)?:查找集合中是否含有对象o
Iterator?iterator()?:返回一个迭代器,用来访问集合中的各个元素
(3)?组操作?:作用于元素组或整个集合
boolean?containsAll(Collection?c):?查找集合中是否含有集合c?中所有元素
boolean?addAll(Collection?c)?:?将集合c?中所有元素添加给该集合
void?clear():?删除集合中所有元素
void?removeAll(Collection?c)?:?从集合中删除集合c?中的所有元素
void?retainAll(Collection?c)?:?从集合中删除集合c?中不包含的元素
(4)?Collection转换为Object数组?:
Object[]?toArray()?:返回一个内含集合所有元素的array
Object[]?toArray(Object[]?a)?:返回一个内含集合所有元素的array。运行期返回的array和参数a的型别相同,需要转换为正确型别。
此外,您还可以把集合转换成其它任何其它的对象数组。但是,您不能直接把集合转换成基本数据类型的数组,因为集合必须持有对象。
“斜体接口方法是可选的。因为一个接口实现必须实现所有接口方法,调用程序就需要一种途径来知道一个可选的方法是不是不受支持。如果调用一种可选方法?时,一个?UnsupportedOperationException?被抛出,则操作失败,因为方法不受支持。此异常类继承?RuntimeException?类,避免了将所有集合操作放入?try-catch?块。”
Collection不提供get()方法。如果要遍历Collectin中的元素,就必须用Iterator。
2.List接口对Collection进行了简单的扩充,它的具体实现类常用的有ArrayList和LinkedList。你可以将任何东西放到一个?List容器中,并在需要时从中取出。ArrayList从其命名中可以看出它是一种类似数组的形式进行存储,因此它的随机访问速度极快,而?LinkedList的内部实现是链表,它适合于在链表中间需要频繁进行插入和删除操作。在具体应用时可以根据需要自由选择。前面说的Iterator只?能对容器进行向前遍历,而ListIterator则继承了Iterator的思想,并提供了对List进行双向遍历的方法。
(1)?面向位置的操作包括插入某个元素或?Collection?的功能,还包括获取、除去或更改元素的功能。在?List?中搜索元素可以从列表的头部或尾部开始,如果找到元素,还将报告元素所在的位置?:
void?add(int?index,?Object?element):?在指定位置index上添加元素element
boolean?addAll(int?index,?Collection?c):?将集合c的所有元素添加到指定位置index
Object?get(int?index):?返回List中指定位置的元素
int?indexOf(Object?o):?返回第一个出现元素o的位置,否则返回-1
int?lastIndexOf(Object?o)?:返回最后一个出现元素o的位置,否则返回-1
Object?remove(int?index) :删除指定位置上的元素
Object?set(int?index,?Object?element)?:用元素element取代位置index上的元素,并且返回旧的元素
(2)?List?接口不但以位置序列迭代的遍历整个列表,还能处理集合的子集:
ListIterator?listIterator()?:?返回一个列表迭代器,用来访问列表中的元素
ListIterator?listIterator(int?index)?:?返回一个列表迭代器,用来从指定位置index开始访问列表中的元素
List?subList(int?fromIndex,?int?toIndex)?:返回从指定位置fromIndex(包含)到toIndex(不包含)范围中各个元素的列表视图
“对子列表的更改(如?add()、remove()?和?set()?调用)对底层?List?也有影响。”?“ArrayList?和?LinkedList?都实现?Cloneable?接口,都提供了两个构造函数,一个无参的,一个接受另一个Collection”
LinkedList类
LinkedList类添加了一些处理列表两端元素的方法。
(1)?void?addFirst(Object?o):?将对象o添加到列表的开头
void?addLast(Object?o):将对象o添加到列表的结尾
(2)?Object?getFirst():?返回列表开头的元素
Object?getLast():?返回列表结尾的元素
(3)?Object?removeFirst():?删除并且返回列表开头的元素
Object?removeLast():删除并且返回列表结尾的元素
(4)?LinkedList():?构建一个空的链接列表
LinkedList(Collection?c):?构建一个链接列表,并且添加集合c的所有元素
“使用这些新方法,您就可以轻松的把?LinkedList?当作一个堆栈、队列或其它面向端点的数据结构。”
ArrayList类
ArrayList类封装了一个动态再分配的Object[]数组。每个ArrayList对象有一个capacity。这个capacity表示存储列表中元素的数组的容量。当元素添加到ArrayList时,它的capacity在常量时间内自动增加。
?在向一个ArrayList对象添加大量元素的程序中,可使用ensureCapacity方法增加capacity。这可以减少增加重分配的数量。
?(1)?void?ensureCapacity(int?minCapacity):?将ArrayList对象容量增加minCapacity
(2)?void?trimToSize():?整理ArrayList对象容量为列表当前大小。程序可使用这个操作减少ArrayList对象存储空间。