2008年9月18日

java中的集合

一、用得最多的主要有Set,List,Map,Iterator这几个接口, Set和List接口都是Collection接口的子接口,有很多相同的地方,我们只是撑握了Collection接口的方法,Set和List的用法也就差不多了.
      Set和List 的区别:1、Set是没有顺序的,不能放重复的数据(相同的数据)
                                  2、List是有顺序的,可以存放重复的数据(相同的数据)
Set的实现类常用的主要有两个:HashSet、TreeSet
      我们可以把一类对象添加到集合中,并且按对象的某一个属性进行排序(客户化排序和自然排序)
      1、对TreeSet集进行客户化排序要求写一个类实现Comparator接口,并且重写其中的Compare方法 例:
      客户化排序容易扩展,如果要按其它的属性排序,只需要重新写一个类实现Comparator接口就可以了,
      不需要修改原来的代码。
      class Users
      {
           private String name;
           private int id;
           public Users(String name,int id)
           {
                this.name=name;
                this.id=id;
           }
           public void setName(String name)
           {
                 this.name=name;
           }
           public String getName()
           {
                   return name;
           }
           public void setId(int id)
           {
                  this.id=id;
           }
           public int getId()
           {
                 return id;
           }
           //这里重写了父类的toString方法
           public String toString()
           {
                  return this.name + "\t" + this.id + "\t";
            }
      }
      //这个类实现Comparator接口,并且重写了其中的compare方法
      public class MyComparator implements Comparator
     {
           public int  compare(Object o1,Object o2)
           {
                Users user1=(Users)o1;
                Users user2=(Users)o2;
                if(user1.getId>user2.getId) return 1;
                else if(user1.getId==user2.getId) return 0;
                return -1;
           }
     }
     class  TestComparator
     {
          public static void main(String args[])
          {
               TestComparator.test();
          }
          public static void test()
          {
                  Set   set=new TreeSet(new MyComparator());
                  Users user1=new  Users("张三",17);
                  Users user2=new  Users("李四",13);
                  Users user3=new  Users("王五",19);
                  Users user5=new Users("王五",19);
                  set.add(user1);
                  set.add(user2);
                  set.add(user3);
                  set.add(user5);
                  
                  for(Object obj :set)
                  {
                        System.out.println(obj);
                  }
          }
     }
     2、自然排序,将需要排序的那个类实现Comparable接口并且重写其中的compareTo方法
          例如下:      class Users  implements Comparable
      {
           private String name;
           private int id;
           public Users(String name,int id)
           {
                this.name=name;
                this.id=id;
           }
           public void setName(String name)
           {
                 this.name=name;
           }
           public String getName()
           {
                   return name;
           }
           public void setId(int id)
           {
                  this.id=id;
           }
           public int getId()
           {
                 return id;
           }
           //这里重写了父类的toString方法
           public String toString()
           {
                  return this.name + "\t" + this.id + "\t";
            }
            //重写compareTo方法
             public int compareTo(Object o)
             {
  
                     UserBean user = (UserBean) o;
                     if (this.id > user.id) return 1;
                     else if (this.id == user.id) return 0;
                      return -1;
             }
      }
      3.如果是HashSet自然排序,则要求排序的类重写hashCode方法和equals方法
      二、对List和Set集进行遍历:
       List集有三种方法进行遍历:
       1、通过下标遍历,2使用迭代器进行遍历,3、增强循环进行遍历
       List list=new ArrayList();
       list.add("aa");
       list.add("bb");
       list.add("cc");
       for(int i=0;i<list.size();i++)
      {
          System.out.println(list.get(i));
      }
      
     Iterator it=list.iterator();
     while(it.hasNext())
    {
         System.out.println(it.next());
    }
    
    for(Object obj :list)
    {
          System.out.println(obj);
    }
    三、Vector和ArrayList的区别:
    1、Vector 和ArrayList都实现了List接口,Vector是线程安全的,可以多个线程同时访问,但性能比较差
    2、ArrayList线程不安全,不支持多个线程同时访问,但性能比较好,访问的速度快
    
    四、Map集是以键值对的形式存放的,键不可以重复,值可以重复,如果键重复,会将原来的值覆盖,
     Map集的实现类主要有三个:HashMap,TreeMap,HashTable
    HashMap与HashTable 的区别: 1、HashTable是线程安全的,支持同步。2、HashMap线程不安全,不支持
    同步,但性能比HashTable好
    Map集的遍历:
      1、
      Map map=new HashMap()
      map.put("1","张飞");
      map.put("2","关羽");
      map.put("3","刘备");
      //得到键的集合
      Set set=map.keySet();
      for(Object obj :set)
      {
          System.out.println(map.get(obj));
      }
      2、
      //得到健值对的集合
      Set s=map.entrySet();
       for(Object obj :set)      {
          System.out.println(obj);
      }
   五、对List集进行客户化排序,可以通过Collections类的sort方法,要求传一个List集和一个Comparator对象 例:
      List list=new ArrayList()
      Users user1=new  Users("张三",17);      Users user2=new  Users("李四",13);
      Users user3=new  Users("王五",19);
      Users user5=new Users("王五",19);
      list.add(user1);
      list.add(user2);
      list.add(user3);
      list.add(user5);
      Collections.sort(list,new Mycomparator());
      Iterator it=list.iterator();
      while(it.hasNext())
      {
           System.out.println(it.next());
      }

posted @ 2008-09-20 17:07 nicaini 阅读(210) | 评论 (0)编辑 收藏

Collection和Collections的区别

java.util.Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。
java.util.Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
具体的差别看看Java API文档就知道了。

posted @ 2008-09-20 11:48 nicaini 阅读(319) | 评论 (0)编辑 收藏

Java初学者都必须理解的七大问题

问题一:我声明了什么!

  String s = "Hello world!";
  许多人都做过这样的事情,但是,我们到底声明了什么?回答通常是:一个String,内容是"Hello world!"。这样模糊的回答通常是概念不清的根源。如果要准确的回答,一半的人大概会回答错误。
  这个语句声明的是一个指向对象的引用,名为“s”,可以指向类型为String的任何对象,目前指向"Hello world!"这个String类型的对象。这就是真正发生的事情。我们并没有声明一个String对象,我们只是声明了一个只能指向String对象的引用变量。所以,如果在刚才那句语句后面,如果再运行一句:
  String string = s;
  我们是声明了另外一个只能指向String对象的引用,名为string,并没有第二个对象产生,string还是指向原来那个对象,也就是,和s指向同一个对象。

问题二:"=="和equals方法究竟有什么区别?

  ==操作符专门用来比较变量的值是否相等。
  int a=10;
  int b=10;
  则a==b将是true。

  但:
  String a=new String("foo");
  String b=new String("foo");
  则a==b将返回false。

  对象变量其实是一个引用,它们的值是指向对象所在的内存地址,而不是对象本身。a和b都使用了new操作符,意味着将在内存中产生两个内容为"foo"的字符串,既然是“两个”,它们自然位于不同的内存地址。a和b的值其实是两个不同的内存地址的值,所以使用"=="操作符,结果会是false。虽然,a和b所指的对象,它们的内容都是"foo",应该是“相等”,但是==操作符并不涉及到对象内容的比较。

  对象内容的比较应使用Object对象的equals方法。
  boolean equals(Object o){
return this==o;
  }
  Object对象默认使用了==操作符。所以如果你自创的类没有覆盖equals方法,那你的类使用equals和使用==会得到同样的结果。同样也可以看出,Object的equals方法没有达到equals方法应该达到的目标:比较两个对象内容是否相等。因为答案应该由类的创建者决定,所以Object把这个任务留给了类的创建者。

  例如:
  Class MyClass{
   private String content;
   ...
   boolean equals(Object another){
return true;
}
}
  MyClass类中的equals方法覆盖了父类object类的equals方法。这个实现会导致无论MyClass类的实例内容如何,它们之间的比较永远返回true。
  所以当使用equals方法判断对象的内容是否相等,请不要想当然。因为可能你认为相等,而这个类的创建者不这样认为,而类的equals方法的实现是由他掌握的。

问题三:String和StringBuffer的区别
String类被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。请看下列代码:

  String s = "Hello";
  s = s + " world!";

  s所指向的对象是否改变了呢?在这段代码中,s原先指向一个String对象,内容是"Hello",然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了另一个String对象,内容为"Hello world!",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。

  所以,如果经常对字符串进行各种各样的修改,使用String类来代表字符串的话会引起很大的内存开销。因为String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。并且,这两种类的对象转换十分容易。

  同时,我们还可以知道,如果要使用内容相同的字符串,不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化,把它设置为初始值,应当这样做:

  public class Demo {
   private String s;
   ...
   public Demo {
   s = "Initial Value";
   }
  ...
  }

  而非
  s = new String("Initial Value");

  后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。
  上面的结论还基于这样一个事实:对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。
  至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本,即StringBuffer。

问题四:逻辑与/或 和 短路与/或的区别

逻辑操作符:&(与运算),^(异或运算),|(或运算)。
短路逻辑操作符:&&(并且),||(或者).
短路与/或运算符和逻辑与/或一样可以实现逻辑运算,但是此时有一个重要的区别:用逻辑与/或运算时,不管操作符两边的条件表达式成不成立,它都要进行运算判断,而短路与/或运算不一样了,如果通过左侧的操作数就可以进行它们需要的判断,那么它就不会再计算右侧的操作数了,请看下面的例子:
……
double value=0;
if(value!=0 && 1/value<1000){
System.out.println("The value is not too small.");
}
else{
System.out.println("The value is too small.");
}
……
运行结果:
The value is too small.
结果分析:
照理说应会出现除数为0的错误,但由于条件逻辑操作符是短路操作符,显然,value!=0条件不成立,立即就可作出判断应执行else后的语句,所以它就不再会运算判断1/value<1000了.如果不懂请再看一例:
......
double int1=0,int2=1,int3=1;
if(int1!=0 & (int2=2)==1){
}
System.out.println("int2="+int2);
if(int1!=0 && (int3=2)==1){
}
System.out.println("int3="+int3);
......

运行结果:
int2=2.0
int3=1.0

问题五.实例变量与类变量(静态变量)

可以通过两种方法在类中存储数据──作为实例变量和类变量.实例变量是特定于对象的,如果你有两个对象(即一个类的两个实例),每一个对象中的实例变量独立于另一个对象中的实例变量的;另一方面,两个对象的类变量均指向相同的数据,并因此面保存相同的值,换句话说,类变量被类中的所有对象共享,类变量在声明时比实例变量多一个static.
class Data{
public int intdata=0;//intdata在这儿是实例变量
}
public class Test{
public static void main(String[] args){
Data a,b;
a=new Data ();
b=new Data ();
a.intdata=1;
System.out.println("b.indata="+b.intdata);
}
}
运行结果:
b.intdata=0
结果分析:
可以看出,a.intdata的值虽然变了,但并没有影响b.intdata.但是如果在data类中声明intdata时,在其前面加上static就变成类变量了(即:public static int intdata=0;),则此时运行结果会变为:b.intdata=1
这次a.intdata值的改变可把b.intdata影响了,事实上,对象a和b的类变量均指向相同的数据,所有值一样,这就是类变量的作用.

问题六:实例方法,类方法(静态方法),构造器方法

我们通常所说的方法系指实例方法。类方法(即静态方法)与实例方法最大的区别是:在形式上类方法多一个static,在用法上不必创建对象就可直接调用类方法(而实例方法却一定要先创建对象,再通过对象调用)。
class Add{
static int addNum(int op1,int op2){
return op1+op2;
}
}
public class Test{
public static void main(String[] args){
//直接用类名作为对象调用类方法
System.out.println("addem(2,2)="+Add.addNum(2,2));
}
}
注: 也可按通常的方法,即先创建对象,再调用方法,不过,这时static就无任何意义了。
构造器方法,它是用来初始化对象中的数据的一种方法,创建很容易,只需在类中加上一个与这个类同名的方法,不需要在前面加任何访问说明符或者返回类型,另外,构造器也一样可以象方法一样传递参数.
class Data{
private String data1;//事先声明
Data(String s){
data1=s; /*通过接收数据来初始化变量.(注:不能在构造器内声明变
量,事先在外就要声明.)*/
}
public String getData(){
return data1;
}
}
public class Test{
public static void main(String[] args){
/*通过传递参数调用构造器新建一个对象,再通过对象调用方法得到数据*/
System.out.println((new Data("I love you")).getData());
}
}

问题七:接口与类

类是对一类特定对象的规格说明,我们可以定义类,然后创建类的对象,通过创建类的对象来组合所有属于该类的组件,而接口不能这样做.而接口实质上就是一个常量和抽象方法的集合,要使用一个接口,就需要在类中实现这个接口,然后作为类定义的一部分,编写接口中声明的每一个方法,接口中的方法永远是public,abstract,接口中的常量永远是public static和final,因此不需要为它们说明属性.因为在Java中不支持多重继承,但是,可以用接口来实现类似的功能,这是接口的重要作用之一。
interface anyone{ //定义一个接口
final double PI=3.1416;
void setNumber(int number);
int getNumber();
}
interface anyother{ //定义另一个接口
void setString(String str);
String getString();
}

class Test implement anyone,anyother{ //定义一个类,并使用两个接口
int number;
String str;
public Test(){
}
void setNumber(int number){
this.number=number;
}
void setString(String str){
this.str=str;
}
void int getNumber(){
}//可以为一个空实现.
void String getString(){
}
}

posted @ 2008-09-18 14:03 nicaini 阅读(196) | 评论 (0)编辑 收藏

<2008年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

常用链接

留言簿(1)

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜