载入中。。。 'S bLog
 
载入中。。。
 
载入中。。。
载入中。。。
载入中。。。
载入中。。。
载入中。。。
 
填写您的邮件地址,订阅我们的精彩内容:


 
今天在和同学研究论文时,涉及到了java的可变类与不变类的讨论
[ 2011/11/4 17:19:00 | By: 梦翔儿 ]
 

the performance of mapreduce: an indepth study

论文中 2.3 parsing 节的个人理解:

parsing就是原始数据转为kv对的过程
两种数据,一种是immutable,不可变的,即转完后,该数据是只读,不可修改的,比如说Java的string对象,赋值新的会把旧的对象覆盖,可以理解为线性表,数组(非指针的那种,要独自占内存空间的),这样1万个对象,就要1万个对应的内存空间占用。反之mutalbe是可变的,类似于C++中的指针,可以到处指向,非指向的自动垃圾回收。这样1万个对象,只有一个对象常驻留内存。
创建,immutable对CPU占用过高
在4.3处,用VarCharWritable来代替了string,对文本解码
figure4,5中有对比实验结果

=========

http://zhidao.baidu.com/question/57731044.html

http://kissme.iteye.com/blog/694917

这里有一点不变类的解释

其实我的理解是,不变类占cpu大,但处理string快。可变类,类似于流,占CPU小,但以流处理时,不快。
其实是个CPU占用和速度之间的一个权衡。
hadoop,我倒是觉得用不变类应该比较好。

=======

Java不可变类(基于final类的实现,final类只是不能被继承的类而已)

jdk的可变类和不可变类

所谓不可变类,是指当创建了这个类的实例后,就不允许修改它的属性值。在JDK的基本类库中,所有基本类型的包装类,如Integer和Long类,都是不可变类,java.lang.String也是不可变类,虽然他不是基本类型。

基本类型变量: boolean,byte, char, double ,float, integer, long, short
jdk的不可变类:jdk的java.lang包中 Boolean, Byte, Character, Double, Float, Integer, Long, Short, String.
jdk可变类举例:StringBuffer 可变类,java.util.Date 可变类

1.  可变类和不可变类(Mutable and Immutable Objects)的初步定义:
      可变类:当你获得这个类的一个实例引用时,你可以改变这个实例的内容。
      不可变类:当你获得这个类的一个实例引用时,你不可以改变这个实例的内容。不可变类的实例一但创建,其内在成员变量的值就不能被修改。

  
2. 如何创建一个自己的不可变类:
      .所有成员都是private
      .不提供对成员的改变方法,例如:setXXXX
      .确保所有的方法不会被重载。手段有两种:使用final Class(强不可变类),或者将所有类方法加上final(弱不可变类)。
      .如果某一个类成员不是原始变量(primitive)或者不可变类,必须通过在成员初始化(in)或者get方法(out)时通过深度clone方法,来确保类的不可变。

   3. 一个示例

import java.util.Date;                                         
public final class BrokenPerson                               
{                                                             
  private String firstName;                                   
  private String lastName;                                    
  private Date dob;                                           
                                        
  public BrokenPerson( String firstName,                   public BetterPerson( String firstName,
    String lastName, Date dob)                                             String lastName, Date dob)         
  {                                                        {                                                   
   this.firstName = firstName;                                this.firstName = firstName;        
   this.lastName = lastName;                                  this.lastName = lastName;          
   this.dob = dob; //error                                    this.dob = new Date( dob.getTime() ); //correct
}                                                          }                                                                 
                                                            
  public String getFirstName()
  {
   return this.firstName;
  }
  public String getLastName()
  {
   return this.lastName;
  }
  public Date getDOB()                                       public Date getDOB()                    
  {                                                          {                        
   return this.dob;    //error                                 return new Date( this.dob.getTime() );//correct
  }                                                          }
                                                                                                                          
}



如:String var = "abcd";Long i = 0L;
我们知道,当声明一个变量的时候,变量名实际上是该对象的指针;而我们在函数中传递该变量的时候实际上也是传递的指针.但基本类型传递的是他的实际值;


查看JAVA中的别名效应:
public class TestClass {
public int num;

public void doit(TestClass parm){
System.out.println("parm's num is "+parm.num);
//parm's num is 10
TestClass b = parm;
b.num = 11;
System.out.println("b's num is "+parm.num);
//b's num is 11
System.out.println("new parm's num is "+parm.num);
//new parm's num is 11
}
public static void main(String[] args){
TestClass a = new TestClass();
a.num = 10;
a.doit(a);
}
}

此时,a.num 的值是 11.
为什么?因为我们将 a--指向TestClass类的一个实例的指针,传递给doit();然后在方法中我们声明另一个实例,然后将指针指向了 a .实际上a,b现在都指向了同一个内存区.当修改 b 的属性时,a也受了影响.这就是别名效应


但如果传递的是基本类型,就不会出现。因为基本类型是不可变类;当声明新类,或对类的值做出修改的时候它都会创建一个新的类,然后再进行赋值;如:
String var = "abc";
var = "bcd";
这个过程中实际上创建了两个String 对象;同样,这种现象也发生在Long,Integer等上。


因为String也是不可变类,所以就引出了一个问题:在需要拼接字符串时,我们有时候会通过大量的:
str += "";语句来实现。其实这样是非常影响效率的。因为每一个 += 语句都会创建一个新的对象,并且意味着要清空以前的对象。这时候有另外一个类:StringBuffer 解决了这一问题。对StringBuffer的操作都是在一个对象上的,不会创建新的。


在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的:
String S1 = “This is only a” + “ simple” + “ test”;
StringBuffer sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);


你会很惊讶的发现,生成 String S1 对象的速度简直太快了,而这个时候 StringBuffer 居然速度上根本一点都不占优势。其实这是 JVM 的一个把戏,在 JVM 眼里,这个 
String S1 = “This is only a” + “ simple” + “test”;
其实就是: String S1 = “This is only a simple test”; 所以当然不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的 String 对象的话,速度就没那么快了,譬如:
String S2 = “This is only a”;
String S3 = “ simple”;
String S4 = “ test”;
String S1 = S2 +S3 + S4;
这时候 JVM 会规规矩矩的按照原来的方式去做 在大部分情况下 StringBuffer > String
http://songyishan.iteye.com/blog/991495

 
 
  • 标签:可变类 不变类 
  • 发表评论:
    载入中。。。

     
     
     

    梦翔儿网站 梦飞翔的地方 http://www.dreamflier.net
    中华人民共和国信息产业部TCP/IP系统 备案序号:辽ICP备09000550号

    Powered by Oblog.