Sunspl

          Hello,everyone,i am sun. 天道酬勤,笨鳥先飛.
          隨筆 - 47, 文章 - 0, 評(píng)論 - 24, 引用 - 0
          數(shù)據(jù)加載中……

          JAVA架構(gòu)師學(xué)習(xí)方向

          請(qǐng)點(diǎn)我查閱:JAVA架構(gòu)師

          posted @ 2018-10-26 14:12 JavaSuns 閱讀(182) | 評(píng)論 (0)編輯 收藏

          POI操作

          package cc.dynasoft.struts.action;

          import java.io.FileOutputStream;
          import java.io.IOException;
          import java.util.Iterator;
          import java.util.List;
          import java.util.Vector;

          import org.apache.poi.hssf.usermodel.HSSFCell;
          import org.apache.poi.hssf.usermodel.HSSFCellStyle;
          import org.apache.poi.hssf.usermodel.HSSFFont;
          import org.apache.poi.hssf.usermodel.HSSFFooter;
          import org.apache.poi.hssf.usermodel.HSSFHeader;
          import org.apache.poi.hssf.usermodel.HSSFPrintSetup;
          import org.apache.poi.hssf.usermodel.HSSFRow;
          import org.apache.poi.hssf.usermodel.HSSFSheet;
          import org.apache.poi.hssf.usermodel.HSSFWorkbook;
          import org.apache.poi.hssf.util.HSSFColor;
          import org.apache.poi.hssf.util.Region;

          import cc.dynasoft.bean.Department;

          ///import org.apache.poi.hssf.record.HeaderRecorder;

          public class OutputExcel {

          public static boolean outputExcel(ExcelArgs args, List title, List list) {
           try {
            int cellNum = args.getCellNum(); // workbook
            int rowNum = args.getRowNum();
            /**
             * 建立表格設(shè)置。
             */
            HSSFWorkbook wb = new HSSFWorkbook(); // create the new Workbook
            HSSFSheet sheet = wb.createSheet(args.getSheetName()); // create
            /**
             * 打印設(shè)置
             */
            HSSFPrintSetup hps = sheet.getPrintSetup();
            hps.setPaperSize((short) 9); // 設(shè)置A4紙
            // hps.setLandscape(true); // 將頁(yè)面設(shè)置為橫向打印模式
            sheet.setHorizontallyCenter(true); // 設(shè)置打印頁(yè)面為水平居中
            // sheet.setVerticallyCenter(true); // 設(shè)置打印頁(yè)面為垂直居中
            wb.setPrintArea(0, "$A$2:$e$" + rowNum + 2);// 打印區(qū)域設(shè)置.
            /**
             * 設(shè)置表的Footer
             */
            HSSFFooter footer = sheet.getFooter();
            // 設(shè)置footer的位置和顯示的內(nèi)容
            footer.setCenter("Time:" + HSSFFooter.date());
            footer.setRight("Page " + HSSFFooter.page() + " of "
              + HSSFFooter.numPages());
            /**
             * 設(shè)置表的Header
             */
            // 設(shè)置header的位置,共有三種位置和相應(yīng)的顯示設(shè)置
            HSSFHeader header = sheet.getHeader();
            // header.setRight("Center Header");
            // header.setLeft("Left Header");
            header.setCenter(HSSFHeader.font("Stencil-Normal", "Italic")
              + HSSFHeader.fontSize((short) 30) + args.getHeaderTitle());
            // header.endDoubleUnderline();
            header.startUnderline();
            /**
             * 設(shè)置列的寬度
             */
            sheet.setColumnWidth((short) 2,
              (short) ((30 * 8) / ((double) 1 / 10)));
            sheet.setColumnWidth((short) 3,
              (short) ((40 * 8) / ((double) 1 / 10)));
            sheet.setColumnWidth((short) 4,
              (short) ((50 * 8) / ((double) 1 / 20)));
            /**
             * 創(chuàng)建第一行,也就是顯示的標(biāo)題, 可以高置的高度,單元格的格式,顏色,字體等設(shè)置. 同時(shí)可以合并單元格.
             */
            HSSFRow row0 = sheet.createRow(0); // 創(chuàng)建0行
            row0.setHeight((short) 0x300); // 設(shè)直行的高度.
            HSSFFont font2 = wb.createFont(); // 創(chuàng)建字體格式
            font2.setColor(HSSFFont.SS_NONE); // 設(shè)置單元格字體的顏色.
            font2.setFontHeight((short) 700); // 設(shè)置字體大小
            font2.setFontName("Courier New"); // 設(shè)置單元格字體
            HSSFCell cell0 = row0.createCell((short) 0); // 創(chuàng)建0行0列.
            HSSFCellStyle style3 = wb.createCellStyle(); // 創(chuàng)建單元格風(fēng)格.
            style3.setAlignment(HSSFCellStyle.VERTICAL_CENTER); // 垂直居中
            style3.setAlignment(HSSFCellStyle.ALIGN_CENTER); // /水平居中
            style3.setFont(font2); // 將字體格式加入到單元格風(fēng)格當(dāng)中
            // cell0.setCellType()
            cell0.setCellStyle(style3); // 設(shè)置單元格的風(fēng)格.
            cell0.setCellValue(args.getHeaderTitle()); // 設(shè)置單元的內(nèi)容.
            sheet.addMergedRegion(new Region(0, (short) 0, 0,
              (short) (cellNum - 1)));// 指定合并區(qū)域,前二個(gè)參數(shù)為開始處X,Y坐標(biāo).后二個(gè)為結(jié)束的坐標(biāo).
            /**
             * 設(shè)置其它數(shù)據(jù) 設(shè)置風(fēng)格
             */
            HSSFCellStyle style = wb.createCellStyle();
            style.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 設(shè)置單無格的邊框?yàn)榇煮w
            style.setBottomBorderColor(HSSFColor.BLACK.index); // 設(shè)置單元格的邊框顏色.
            style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
            style.setLeftBorderColor(HSSFColor.BLACK.index);
            style.setBorderRight(HSSFCellStyle.BORDER_THIN);
            style.setRightBorderColor(HSSFColor.BLACK.index);
            style.setBorderTop(HSSFCellStyle.BORDER_THIN);
            style.setTopBorderColor(HSSFColor.BLACK.index);
            // style.setWrapText(true);//文本區(qū)域隨內(nèi)容多少自動(dòng)調(diào)整

            // style.setFillForegroundColor(HSSFColor.LIME.index);
            // style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
            /**
             * 設(shè)置風(fēng)格1
             */
            HSSFCellStyle style1 = wb.createCellStyle();
            style1.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 設(shè)置單無格的邊框?yàn)榇煮w
            style1.setBottomBorderColor(HSSFColor.BLACK.index); // 設(shè)置單元格的邊框顏色.
            style1.setBorderLeft(HSSFCellStyle.BORDER_THIN);
            style1.setLeftBorderColor(HSSFColor.BLACK.index);
            style1.setBorderRight(HSSFCellStyle.BORDER_THIN);
            style1.setRightBorderColor(HSSFColor.BLACK.index);
            style1.setBorderTop(HSSFCellStyle.BORDER_MEDIUM);
            style1.setTopBorderColor(HSSFColor.BLACK.index);
            style1.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);// 最好的設(shè)置Pattern
            // 單元格背景的顯示模式.
            style1.setFillForegroundColor(new HSSFColor.RED().getIndex()); // 設(shè)置單元格背景色;
            style1.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 水平對(duì)齊方式
            // style1.setWrapText(true);//文本區(qū)域隨內(nèi)容多少自動(dòng)調(diào)整
            // style.setFillPattern(HSSFCellStyle.//);
            // 設(shè)置字體Color,首先創(chuàng)建Font對(duì)象,后對(duì)font設(shè)置,然后做為參數(shù)傳給style
            HSSFFont font = wb.createFont();
            font.setColor(HSSFFont.SS_NONE);
            // font.setFontHeightInPoints((short)24);
            font.setFontName("Courier New");
            // font.setItalic(true);
            // font.setStrikeout(true);//給字體加上刪除線
            font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
            style1.setFont(font);
            /**
             *
             * 設(shè)置第零行表格說明行
             *
             *
             *
             */
            HSSFRow row1 = sheet.createRow((short) 1);
            for (int j = 0; j < cellNum; j++) {
             HSSFCell cell = row1.createCell((short) j);
             cell.setCellValue((String) title.get(j));
             cell.setCellStyle(style1);
            }
            // style.setFillPattern(HSSFCellStyle.NO_FILL);

            /**
             * 設(shè)置表的內(nèi)容主體
             */

            Iterator iter = list.iterator();
            for (int i = 2; iter.hasNext(); i++) {
             Department dep = (Department) iter.next();
             HSSFRow row = sheet.createRow((short) i);
             HSSFCell cell5 = row.createCell((short) 0);
             HSSFCell cell1 = row.createCell((short) 1);
             HSSFCell cell2 = row.createCell((short) 2);
             HSSFCell cell3 = row.createCell((short) 3);
             HSSFCell cell4 = row.createCell((short) 4);
             cell5.setCellValue(dep.getId());
             cell5.setCellStyle(style);
             cell1.setCellValue(dep.getParentId());
             cell1.setCellStyle(style);
             cell2.setCellValue(dep.getName());
             cell2.setCellStyle(style);
             cell3.setCellValue(dep.getDescription());
             cell3.setCellStyle(style);
             cell4.setCellValue(dep.getImagePath());
             cell4.setCellStyle(style);
            }
            // Write the output to a file}
            // FileOutputStream fileOut = new
            // FileOutputStream(args.getPath()+args.getFileName());
            /**
             * 對(duì)文件進(jìn)行輸出操作。
             */
            FileOutputStream fileOut = new FileOutputStream(args
              .getPathAndName());
            wb.write(fileOut);
            // fileOut.close();
           } catch (IOException ex) {
            ex.printStackTrace();
           } catch (Exception ex) {
            ex.printStackTrace();
           }
           return true;
          }

          }

          posted @ 2009-06-13 19:52 JavaSuns 閱讀(612) | 評(píng)論 (0)編輯 收藏

          linux創(chuàng)建文件夾命令

          mkdir /home/u1 創(chuàng)建文件夾/home/u1
          chown oracle /home/u1 表示改變目錄所有者為oracle賬戶;
          chgrp dba /home/u1 改變/home/u1目錄為dba所有;
          chmod 755 /home/u1 表示oracle賬戶對(duì)/home/u1目錄有755權(quán)限;
          rmdir /home/u1 表示刪除/home/u1目錄

          hostname可以查看linux的計(jì)算機(jī)名;
          whoami可以查看當(dāng)前用戶;
          pwd顯示當(dāng)前路徑;
          df查看系統(tǒng)的硬件信息
          ls -lrt l表示顯示詳細(xì)列表,-t表示按時(shí)間排序,-r反向排序

          cat orcl_ora_3436.trc|grep bucket

          以下查看相關(guān)文件內(nèi)容:
          more /etc/oratab
          cat /etc/passwd
          cat /etc/group

          posted @ 2008-07-28 09:01 JavaSuns 閱讀(38656) | 評(píng)論 (4)編輯 收藏

          Linux中復(fù)制文件或目錄的命令(為了響應(yīng)新工作,要學(xué)習(xí)一下LINUX)

          copy命令  

          該命令的功能是將給出的文件或目錄拷貝到另一文件或目錄中,同MSDOS下的copy命令一樣,功能十分強(qiáng)大。  

          語法: cp [選項(xiàng)] 源文件或目錄 目標(biāo)文件或目錄  

          說明:該命令把指定的源文件復(fù)制到目標(biāo)文件或把多個(gè)源文件復(fù)制到目標(biāo)目錄中。  

          該命令的各選項(xiàng)含義如下:

          - a 該選項(xiàng)通常在拷貝目錄時(shí)使用。它保留鏈接、文件屬性,并遞歸地拷貝目錄,其作用等于dpR選項(xiàng)的組合。 

          - d 拷貝時(shí)保留鏈接。  

          - f 刪除已經(jīng)存在的目標(biāo)文件而不提示。  

          - i 和f選項(xiàng)相反,在覆蓋目標(biāo)文件之前將給出提示要求用戶確認(rèn)?;卮饄時(shí)目標(biāo)文件將被覆蓋,是交互式拷貝。  

          - p 此時(shí)cp除復(fù)制源文件的內(nèi)容外,還將把其修改時(shí)間和訪問權(quán)限也復(fù)制到新文件中。  

          - r 若給出的源文件是一目錄文件,此時(shí)cp將遞歸復(fù)制該目錄下所有的子目錄和文件。此時(shí)目標(biāo)文件必須為一個(gè)目錄名。 

          - l 不作拷貝,只是鏈接文件。  

          需要說明的是,為防止用戶在不經(jīng)意的情況下用cp命令破壞另一個(gè)文件,如用戶指定的目標(biāo)文件名已存在,用cp命令拷貝文件后,這個(gè)文件就會(huì)被新源文件覆蓋,因此,建議用戶在使用cp命令拷貝文件時(shí),最好使用i選項(xiàng)。

          posted @ 2008-07-28 08:59 JavaSuns 閱讀(2325) | 評(píng)論 (0)編輯 收藏

          解析oracle的rownum(學(xué)習(xí))

          對(duì)于rownum來說它是oracle系統(tǒng)順序分配為從查詢返回的行的編號(hào),返回的第一行分配的是1,第二行是2,依此類推,這個(gè)偽字段可以用于限制查詢返回的總行數(shù),而且rownum不能以任何表的名稱作為前綴。
           舉例說明:
          例如表:student(學(xué)生)表,表結(jié)構(gòu)為:
          ID       char(6)      --學(xué)號(hào)
          name    VARCHAR2(10)   --姓名
          create table student (ID char(6), name VARCHAR2(100));
          insert into sale values('200001',‘張一’);
          insert into sale values('200002',‘王二’);
          insert into sale values('200003',‘李三’);
          insert into sale values('200004',‘趙四’);
          commit;
          (1) rownum 對(duì)于等于某值的查詢條件
          如 果希望找到學(xué)生表中第一條學(xué)生的信息,可以使用rownum=1作為條件。但是想找到學(xué)生表中第二條學(xué)生的信息,使用rownum=2結(jié)果查不到數(shù)據(jù)。因 為rownum都是從1開始,但是1以上的自然數(shù)在rownum做等于判斷是時(shí)認(rèn)為都是false條件,所以無法查到rownum = n(n>1的自然數(shù))。
          SQL> select rownum,id,name from student where rownum=1;(可以用在限制返回記錄條數(shù)的地方,保證不出錯(cuò),如:隱式游標(biāo))
          SQL> select rownum,id,name from student where rownum=1;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
                   1 200001 張一
          SQL> select rownum,id,name from student where rownum =2;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
          (2)rownum對(duì)于大于某值的查詢條件
             如果想找到從第二行記錄以后的記錄,當(dāng)使用rownum>2是查不出記錄的,原因是由于rownum是一個(gè)總是從1開始的偽列,Oracle 認(rèn)為rownum> n(n>1的自然數(shù))這種條件依舊不成立,所以查不到記錄
          SQL> select rownum,id,name from student where rownum >2;
          ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
          那如何才能找到第二行以后的記錄呀。可以使用以下的子查詢方法來解決。注意子查詢中的rownum必須要有別名,否則還是不會(huì)查出記錄來,這是因?yàn)閞ownum不是某個(gè)表的列,如果不起別名的話,無法知道rownum是子查詢的列還是主查詢的列。
          SQL>select * from(select rownum no ,id,name from student) where no>2;
                  NO ID     NAME
          ---------- ------ ---------------------------------------------------
                   3 200003 李三
                   4 200004 趙四
          SQL> select * from(select rownum,id,name from student)where rownum>2;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
          (3)rownum對(duì)于小于某值的查詢條件
          如果想找到第三條記錄以前的記錄,當(dāng)使用rownum<3是能得到兩條記錄的。顯然rownum對(duì)于rownum<n((n>1的自然數(shù))的條件認(rèn)為是成立的,所以可以找到記錄。
          SQL> select rownum,id,name from student where rownum <3;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
                  1 200001 張一
                  2 200002 王二
          綜 上幾種情況,可能有時(shí)候需要查詢r(jià)ownum在某區(qū)間的數(shù)據(jù),那怎么辦呀從上可以看出rownum對(duì)小于某值的查詢條件是人為true的,rownum對(duì) 于大于某值的查詢條件直接認(rèn)為是false的,但是可以間接的讓它轉(zhuǎn)為認(rèn)為是true的。那就必須使用子查詢。例如要查詢r(jià)ownum在第二行到第三行之 間的數(shù)據(jù),包括第二行和第三行數(shù)據(jù),那么我們只能寫以下語句,先讓它返回小于等于三的記錄行,然后在主查詢中判斷新的rownum的別名列大于等于二的記 錄行。但是這樣的操作會(huì)在大數(shù)據(jù)集中影響速度。
          SQL> select * from (select rownum no,id,name from student where rownum<=3 ) where no >=2;
                  NO ID     NAME
          ---------- ------ ---------------------------------------------------
                   2 200002 王二
                   3 200003 李三
          (4)rownum和排序
          Oracle中的rownum的是在取數(shù)據(jù)的時(shí)候產(chǎn)生的序號(hào),所以想對(duì)指定排序的數(shù)據(jù)去指定的rowmun行數(shù)據(jù)就必須注意了。
          SQL> select rownum ,id,name from student order by name;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
                   3 200003 李三
                   2 200002 王二
                   1 200001 張一
                   4 200004 趙四
          可以看出,rownum并不是按照name列來生成的序號(hào)。系統(tǒng)是按照記錄插入時(shí)的順序給記錄排的號(hào),rowid也是順序分配的。為了解決這個(gè)問題,必須使用子查詢
          SQL> select rownum ,id,name from (select * from student order by name);
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
                   1 200003 李三
                   2 200002 王二
                   3 200001 張一
                   4 200004 趙四
          這樣就成了按name排序,并且用rownum標(biāo)出正確序號(hào)(有小到大)

          posted @ 2008-06-26 10:23 JavaSuns 閱讀(434) | 評(píng)論 (0)編輯 收藏

          Java里的list,set,map操作方法(練習(xí))

          //ArrayList
          {
          ArrayList arraylist=new ArrayList();
          arraylist.add(0,"end");//指定索引加入值
          //需注意的是,如果現(xiàn)有2個(gè)值,我加入索引為5的那么就會(huì)出現(xiàn)異常
          for(int i=0;i<2;i++){
          arraylist.add(i,String.valueOf(i));
          }
          System.out.println("ArrayList:");
          for(int i=0;i<arraylist.size();i++){
          System.out.print(arraylist.get(i)+";");
          }
          arraylist.add("0");//直接加入值到ArrayList的最后
          arraylist.add("0");
          System.out.print("\nArrayList\'s lastIndexOf(\"0\") is "+arraylist.lastIndexOf("0"));
          }
          //Arrays
          {
          String []array=new String[]{"a","b","c"};
          List list=Arrays.asList(array);
          System.out.println("\nArrays:");
          for(int i=0;i<list.size();i++){
          System.out.print(list.get(i)+";");
          }
          System.out.print("\nArrays\'s length is "+array.length);//打印數(shù)組的長(zhǎng)度
          }
          //Collections
          {
          String []array=new String[]{"a","b","c"};
          List list=Arrays.asList(array);
          Collections.fill(list,"Fill");//用Fill填充全部元素
          System.out.println("\nCollections:");
          for(int i=0;i<list.size();i++){
          System.out.print(list.get(i)+";");
          }
          array=new String[]{"1","2","3"};
          List list2=Arrays.asList(array);
          Collections.copy(list,list2);//拷貝list2的數(shù)據(jù)進(jìn)list
          System.out.println("\n"+list);
          Collections.swap(list,2,1);//調(diào)換索引為1和2的元素的位置
          System.out.println(list);
          }
          //EventObject
          {
          String s="hello";
          String s2=s;
          EventObject eventobject=new EventObject(s);//一個(gè)準(zhǔn)容器類型,確切的歸類它不是容器
          System.out.println("EventObject:");
          System.out.println(eventobject.getSource());
          System.out.println(eventobject.equals(s2));
          }
          //HashMap
          {
          HashMap hashmap=new HashMap();//一個(gè)速度最快的容器
          hashmap.put("0","c");
          hashmap.put("1","a");
          hashmap.put("2","b");
          hashmap.put("3","a");
          System.out.println("HashMap:");
          System.out.println(hashmap);//該容器有其內(nèi)部的排序方式
          Set set=hashmap.keySet();//獲取全部鍵
          Iterator iterator=set.iterator();
          while(iterator.hasNext()){
          System.out.print(hashmap.get(iterator.next())+";");
          }
          }
          //HashSet
          {
          HashSet hashset=new HashSet();//一個(gè)絕對(duì)不能重復(fù)的類型
          hashset.add("c");
          hashset.add("b");
          hashset.add("a");
          hashset.add("a");
          hashset.add("b");
          System.out.println("\nHashSet:");
          System.out.println(hashset);
          Iterator iterator=hashset.iterator();//取出元素
          while(iterator.hasNext()){
          System.out.print(iterator.next()+";");
          }
          }
          //Hashtable
          {
          Hashtable hashtable=new Hashtable();//一個(gè)完全可以由其他容器替換的老容器類型
          hashtable.put("0","c");
          hashtable.put("1","a");
          hashtable.put("3","c");
          hashtable.put("2","b");
          System.out.println("\nHashtable:");
          Enumeration enumeration=hashtable.elements();//獲取元素,Enumeration已經(jīng)不是主流,Iterator是它的下一代替代品
          while(enumeration.hasMoreElements()){
          System.out.print(enumeration.nextElement()+";");
          }
          }
          //IdentityHashMap
          {
          IdentityHashMap identityhashmap=new IdentityHashMap();
          identityhashmap.put("0","c");
          identityhashmap.put("1","a");
          identityhashmap.put("3","b");
          identityhashmap.put("2","a");
          System.out.println("\nIdentityHashMap:");
          System.out.println(identityhashmap);
          System.out.println(identityhashmap.containsKey("3"));//是否包含這個(gè)鍵
          System.out.println(identityhashmap.containsValue("a"));//是否包含值
          Set set=identityhashmap.entrySet();//傳為Set類型
          System.out.println(set);
          set=identityhashmap.keySet();//全部鍵
          System.out.println(set);
          }
          //LinkedHashMap
          {
          LinkedHashMap linkedhashmap=new LinkedHashMap();
          linkedhashmap.put("0","b");
          linkedhashmap.put("2","a");
          linkedhashmap.put("1","c");
          linkedhashmap.put("3","b");
          System.out.println("LinkedHashMap:");
          System.out.println(linkedhashmap);
          System.out.println(linkedhashmap.containsKey("2"));//是否包含這個(gè)鍵
          System.out.println(linkedhashmap.containsValue("c"));//是否包含值
          Set set=linkedhashmap.keySet();
          Iterator iterator=set.iterator();
          while(iterator.hasNext()){
          System.out.print(linkedhashmap.get(iterator.next())+";");
          }
          }
          //LinkedHashSet
          {
          LinkedHashSet linkedhashset=new LinkedHashSet();//它包含了幾種Set的屬性但卻沒有自己的特色
          linkedhashset.add("c");
          linkedhashset.add("a");
          linkedhashset.add("a");
          linkedhashset.add("b");
          System.out.println("\nLinkedHashSet:");
          System.out.println(linkedhashset);
          System.out.println(linkedhashset.contains("a"));//是否包含對(duì)象
          Iterator iterator=linkedhashset.iterator();
          while(iterator.hasNext()){
          System.out.print(iterator.next()+";");
          }
          }
          //LinkedList
          {
          LinkedList linkedlist=new LinkedList();//自由使用是它的特色
          linkedlist.add("a");
          linkedlist.add(1,"c");
          linkedlist.addLast("b");
          linkedlist.addFirst("d");
          System.out.println("\nLinkedList:");
          System.out.println(linkedlist);
          //linkedlist.clear();//該方法清空容器
          //linkedlist.remove(0);//刪除索引為0的元素
          //linkedlist.remove("d");//刪除值為d的元素
          //linkedlist.removeFirst();//刪除第一個(gè)元素
          //linkedlist.removeLast();//刪除最后一個(gè)元素
          for(int i=0;i<linkedlist.size();i++){
          System.out.print(linkedlist.get(i)+";");
          }
          }
          //Stack
          {
          Stack stack=new Stack();//堆棧
          stack.add("b");
          stack.add(0,"c");
          stack.push("d");
          stack.add("e");
          stack.push("a");
          Enumeration enumeration=stack.elements();
          System.out.println("\nStack:");
          while(enumeration.hasMoreElements()){
          System.out.print(enumeration.nextElement()+";");
          }
          //后進(jìn)先出
          System.out.println("\n"+stack.peek());
          System.out.println(stack.pop());
          System.out.println(stack.contains("d")+";"+stack.contains("a"));//是否包含該元素,有趣的事情發(fā)生了
          System.out.println(stack.search("c"));//非常有用的屬性,檢索,但是由后向前的排列
          }
          //TreeMap
          {
          TreeMap treemap=new TreeMap();
          treemap.put("0","d");
          treemap.put("2","a");
          treemap.put("1","b");
          treemap.put("3","c");
          System.out.println("\nTreeMap:");//可以對(duì)鍵排序
          System.out.println(treemap);
          System.out.println(treemap.firstKey());//返回第一個(gè)鍵
          Set set=treemap.keySet();
          Iterator iterator=set.iterator();
          while(iterator.hasNext()){
          System.out.print(treemap.get(iterator.next())+";");
          }
          }
          //TreeSet
          {
          TreeSet treeset=new TreeSet();//自動(dòng)排序內(nèi)容
          treeset.add("b");
          treeset.add("a");
          treeset.add("c");
          treeset.add("d");
          System.out.println("\nTreeSet:");
          System.out.println(treeset);
          System.out.println(treeset.first());//返回第一個(gè)元素
          Iterator iterator=treeset.iterator();
          while(iterator.hasNext()){
          System.out.print(iterator.next()+";");
          }
          }
          //Vector
          {
          Vector vector=new Vector();
          vector.add(0,"b");
          vector.add("a");
          vector.addElement("d");
          vector.add("c");
          System.out.println("\nVector:");
          System.out.println(vector);
          vector.set(2,"h");//替換掉指定索引的元素
          System.out.println(vector);
          Object []str=vector.toArray();
          for(int i=0;i<str.length;i++){
          System.out.print(str[i]+";");
          }
          vector.setSize(2);//重新設(shè)置大小為2
          System.out.println("\n"+vector);
          }
          //WeakHashMap
          {
          WeakHashMap weakhashmap=new WeakHashMap();
          weakhashmap.put("1","b");
          weakhashmap.put("2","c");
          weakhashmap.put("0","d");
          weakhashmap.put("3","a");
          System.out.println("\nWeakHashMap:");
          System.out.println(weakhashmap);
          System.out.println(weakhashmap.containsKey("3"));//是否包含鍵
          System.out.println(weakhashmap.containsValue("d"));//是否包含值
          Set set=weakhashmap.entrySet();
          Iterator iterator=set.iterator();
          while(iterator.hasNext()){
          System.out.print(iterator.next()+";");
          }
          //weakhashmap.remove("2");//刪除該鍵對(duì)應(yīng)的值
          //weakhashmap.get("1");//獲取指定鍵的值
          }
          }

          posted @ 2008-06-25 17:33 JavaSuns 閱讀(3885) | 評(píng)論 (0)編輯 收藏

          map,set,list,等JAVA中集合解析(了解)

          在JAVA的util包中有兩個(gè)所有集合的父接口Collection和Map,它們的父子關(guān)系:

                     java.util
                  +Collection 這個(gè)接口extends自 --java.lang.Iterable接口
                     +List 接口
                        -ArrayList 類
                        -LinkedList 類
                        -Vector 類     此類是實(shí)現(xiàn)同步的

                     +Queue 接口
                        +不常用,在此不表.

                     +Set 接口
                        +SortedSet 接口
                           -TreeSet 類
                        -HashSet

                  +Map 接口
                    -HashMap 類 (除了不同步和允許使用 null 鍵/值之外,與 Hashtable 大致相同.)
                    -Hashtable 類 此類是實(shí)現(xiàn)同步的,不允許使用 null 鍵值
                    +SortedMap 接口
                       -TreeMap 類

                    以下對(duì)眾多接口和類的簡(jiǎn)單說明:首先不能不先說一下數(shù)組(Array)
                 
          一、Array , Arrays

          Java所有“存儲(chǔ)及隨機(jī)訪問一連串對(duì)象”的做法,array是最有效率的一種。

          1、
          效率高,但容量固定且無法動(dòng)態(tài)改變。
          array還有一個(gè)缺點(diǎn)是,無法判斷其中實(shí)際存有多少元素,length只是告訴我們array的容量。

          2、Java中有一個(gè)Arrays類,專門用來操作array。
                 arrays中擁有一組static函數(shù),
          equals():比較兩個(gè)array是否相等。array擁有相同元素個(gè)數(shù),且所有對(duì)應(yīng)元素兩兩相等。
          fill():將值填入array中。
          sort():用來對(duì)array進(jìn)行排序。
          binarySearch():在排好序的array中尋找元素。
          System.arraycopy():array的復(fù)制。


          二、Collection , Map

          若撰寫程序時(shí)不知道究竟需要多少對(duì)象,需要在空間不足時(shí)自動(dòng)擴(kuò)增容量,則需要使用容器類庫(kù),array不適用。

          1、Collection 和 Map 的區(qū)別

          容器內(nèi)每個(gè)為之所存儲(chǔ)的元素個(gè)數(shù)不同。
          Collection類型者,每個(gè)位置只有一個(gè)元素。
          Map類型者,持有 key-value pair,像個(gè)小型數(shù)據(jù)庫(kù)。

          2、Java2容器類類庫(kù)的用途是“保存對(duì)象”,它分為兩類,各自旗下的子類關(guān)系

          Collection
                 --List:將以特定次序存儲(chǔ)元素。所以取出來的順序可能和放入順序不同。
                       --ArrayList / LinkedList / Vector
                 --Set : 不能含有重復(fù)的元素
                       --HashSet /TreeSet
          Map
                 --HashMap
              --HashTable
              --TreeMap

           Map----一組成對(duì)的“鍵值對(duì)”對(duì)象,即其元素是成對(duì)的對(duì)象,最典型的應(yīng)用就是數(shù)據(jù)字典,并且還有其它廣泛的應(yīng)用。另外,Map可以返回其所有鍵組成的Set和其所有值組成的Collection,或其鍵值對(duì)組成的Set,并且還可以像數(shù)組一樣擴(kuò)展多維Map,只要讓Map中鍵值對(duì)的每個(gè)“值”是一個(gè)Map即可。

           Collection下 1.迭代器

            迭代器是一種設(shè)計(jì)模式,它是一個(gè)對(duì)象,它可以遍歷并選擇序列中的對(duì)象,而開發(fā)人員不需要了解該序列的底層結(jié)構(gòu)。迭代器通常被稱為“輕量級(jí)”對(duì)象,因?yàn)閯?chuàng)建它的代價(jià)小。

            Java中的Iterator功能比較簡(jiǎn)單,并且只能單向移動(dòng):

            (1) 使用方法iterator()要求容器返回一個(gè)Iterator。第一次調(diào)用Iterator的next()方法時(shí),它返回序列的第一個(gè)元素。注意:iterator()方法是java.lang.Iterable接口,被Collection繼承。


            (2) 使用next()獲得序列中的下一個(gè)元素。

            (3) 使用hasNext()檢查序列中是否還有元素。

            (4) 使用remove()將迭代器新返回的元素刪除。

            Iterator是Java迭代器最簡(jiǎn)單的實(shí)現(xiàn),為L(zhǎng)ist設(shè)計(jì)的ListIterator具有更多的功能,它可以從兩個(gè)方向遍歷List,也可以從List中插入和刪除元素。

            2.List的功能方法

            List(interface): 次序是List最重要的特點(diǎn);它確保維護(hù)元素特定的順序。List為Collection添加了許多方法,使得能夠向List中間插入與移除元素(只推薦LinkedList使用)。一個(gè)List可以生成ListIterator,使用它可以從兩個(gè)方向遍歷List,也可以從List中間插入和刪除元素。

            ArrayList: 由數(shù)組實(shí)現(xiàn)的List。它允許對(duì)元素進(jìn)行快速隨機(jī)訪問,但是向List中間插入與移除元素的速度很慢。ListIterator只應(yīng)該用來由后向前遍歷ArrayList,而不是用來插入和刪除元素,因?yàn)檫@比LinkedList開銷要大很多。

            LinkedList: 由列表實(shí)現(xiàn)的List。對(duì)順序訪問進(jìn)行了優(yōu)化,向List中間插入與刪除得開銷不大,隨機(jī)訪問則相對(duì)較慢(可用ArrayList代替)。它具有方法addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast(),這些方法(沒有在任何接口或基類中定義過)使得LinkedList可以當(dāng)作堆棧、隊(duì)列和雙向隊(duì)列使用。

            3.Set的功能方法

            Set(interface): 存入Set的每個(gè)元素必須是唯一的,這也是與List不同的,因?yàn)镾et不保存重復(fù)元素。加入Set的Object必須定義equals()方法以確保對(duì)象的唯一性。Set與Collection有完全一樣的接口。Set接口不保證維護(hù)元素的次序。

            HashSet: HashSet能快速定位一個(gè)元素,存入HashSet的對(duì)象必須定義hashCode()。

            TreeSet: 保持次序的Set,底層為樹結(jié)構(gòu)。使用它可以從Set中提取有序的序列。

            LinkedHashSet: 具有HashSet的查詢速度,且內(nèi)部使用鏈表維護(hù)元素的順序(插入的次序)。于是在使用迭代器遍歷Set時(shí),結(jié)果會(huì)按元素插入的次序顯示。

            HashSet采用散列函數(shù)對(duì)元素進(jìn)行排序,這是專門為快速查詢而設(shè)計(jì)的;TreeSet采用紅黑樹的數(shù)據(jù)結(jié)構(gòu)進(jìn)行排序元素;LinkedHashSet內(nèi)部使用散列以加快查詢速度,同時(shí)使用鏈表維護(hù)元素的次序,使得看起來元素是以插入的順序保存的。需要注意的是,生成自己的類時(shí),Set需要維護(hù)元素的存儲(chǔ)順序,因此要實(shí)現(xiàn)Comparable接口并定義compareTo()方法。

          3、其他特征

          *     List,Set,Map將持有對(duì)象一律視為Object型別。
          *     Collection、List、Set、Map都是接口,不能實(shí)例化。
                繼承自它們的 ArrayList, Vector, HashTable, HashMap是具象class,這些才可被實(shí)例化。
          *     vector容器確切知道它所持有的對(duì)象隸屬什么型別。vector不進(jìn)行邊界檢查。


          三、Collections

          Collections是針對(duì)集合類的一個(gè)幫助類。提供了一系列靜態(tài)方法實(shí)現(xiàn)對(duì)各種集合的搜索、排序、線程完全化等操作。
          相當(dāng)于對(duì)Array進(jìn)行類似操作的類——Arrays。
          如,Collections.max(Collection coll); 取coll中最大的元素。
                 Collections.sort(List list); 對(duì)list中元素排序

          四、如何選擇?

          1、容器類和Array的區(qū)別、擇取
                *     容器類僅能持有對(duì)象引用(指向?qū)ο蟮闹羔槪?,而不是將?duì)象信息copy一份至數(shù)列某位置。
                *     一旦將對(duì)象置入容器內(nèi),便損失了該對(duì)象的型別信息。

          2、
               *     在各種Lists中,最好的做法是以ArrayList作為缺省選擇。當(dāng)插入、刪除頻繁時(shí),使用LinkedList();
                  Vector總是比ArrayList慢,所以要盡量避免使用。
               *     在各種Sets中,HashSet通常優(yōu)于HashTree(插入、查找)。只有當(dāng)需要產(chǎn)生一個(gè)經(jīng)過排序的序列,才用TreeSet。
                  HashTree存在的唯一理由:能夠維護(hù)其內(nèi)元素的排序狀態(tài)。
               *     在各種Maps中
                  HashMap用于快速查找。
               *     當(dāng)元素個(gè)數(shù)固定,用Array,因?yàn)锳rray效率是最高的。

          結(jié)論:最常用的是ArrayList,HashSet,HashMap,Array。而且,我們也會(huì)發(fā)現(xiàn)一個(gè)規(guī)律,用TreeXXX都是排序的。


          注意:

          1、Collection沒有g(shù)et()方法來取得某個(gè)元素。只能通過iterator()遍歷元素。
          2、Set和Collection擁有一模一樣的接口。
          3、List,可以通過get()方法來一次取出一個(gè)元素。使用數(shù)字來選擇一堆對(duì)象中的一個(gè),get(0)...。(add/get)
          4、一般使用ArrayList。用LinkedList構(gòu)造堆棧stack、隊(duì)列queue

          5、Map用 put(k,v) / get(k),還可以使用containsKey()/containsValue()來檢查其中是否含有某個(gè)key/value。
                HashMap會(huì)利用對(duì)象的hashCode來快速找到key。
              *     hashing
                    哈希碼就是將對(duì)象的信息經(jīng)過一些轉(zhuǎn)變形成一個(gè)獨(dú)一無二的int值,這個(gè)值存儲(chǔ)在一個(gè)array中。
                    我們都知道所有存儲(chǔ)結(jié)構(gòu)中,array查找速度是最快的。所以,可以加速查找。
                
                    發(fā)生碰撞時(shí),讓array指向多個(gè)values。即,數(shù)組每個(gè)位置上又生成一個(gè)梿表。

          6、Map中元素,可以將key序列、value序列單獨(dú)抽取出來。
          使用keySet()抽取key序列,將map中的所有keys生成一個(gè)Set。
          使用values()抽取value序列,將map中的所有values生成一個(gè)Collection。

          為什么一個(gè)生成Set,一個(gè)生成Collection?那是因?yàn)椋琸ey總是獨(dú)一無二的,value允許重復(fù)。

          posted @ 2008-06-25 17:32 JavaSuns 閱讀(11793) | 評(píng)論 (1)編輯 收藏

          項(xiàng)目成功的12個(gè)關(guān)鍵原則(學(xué)習(xí))

          1、項(xiàng)目經(jīng)理必須關(guān)注項(xiàng)目成功的三個(gè)標(biāo)準(zhǔn)

          簡(jiǎn)單地說,一是準(zhǔn)時(shí);二是預(yù)算控制在既定的范圍內(nèi);三是質(zhì)量得到經(jīng)理和用戶們的贊許。項(xiàng)目經(jīng)理必須保證項(xiàng)目小組的每一位成員都能對(duì)照上面三個(gè)標(biāo)準(zhǔn)來進(jìn)行工作。

          2、任何事都應(yīng)當(dāng)先規(guī)劃再執(zhí)行

          就項(xiàng)目管理而言,很多專家和實(shí)踐人員都同意這樣一個(gè)觀點(diǎn):需要項(xiàng)目經(jīng)理投入的最重要的一件事就是規(guī)劃。只有詳細(xì)而系統(tǒng)的由項(xiàng)目小組成員參與的規(guī)劃才是項(xiàng)目成功的唯一基礎(chǔ)。當(dāng)現(xiàn)實(shí)的世界出現(xiàn)了一種不適于計(jì)劃生存的環(huán)境時(shí),項(xiàng)目經(jīng)理應(yīng)制定一個(gè)新的計(jì)劃來反映環(huán)境的變化。規(guī)劃、規(guī)劃、再規(guī)劃就是項(xiàng)目經(jīng)理的一種生活方式。

          3、項(xiàng)目經(jīng)理必須以自己的實(shí)際行動(dòng)向項(xiàng)目小組成員傳遞一種緊迫感

          由于項(xiàng)目在時(shí)間、資源和經(jīng)費(fèi)上都是有限的,項(xiàng)目最終必須完成。但項(xiàng)目小組成員大多有自己的愛好,項(xiàng)目經(jīng)理應(yīng)讓項(xiàng)目小組成員始終關(guān)注項(xiàng)目的目標(biāo)和截止期限。例如,可以定期檢查,可以召開例會(huì),可以制作一些提醒的標(biāo)志置于項(xiàng)目的場(chǎng)所。

          4、成功的項(xiàng)目應(yīng)使用一種可以度量且被證實(shí)的項(xiàng)目生命周期

          標(biāo)準(zhǔn)的信息系統(tǒng)開發(fā)模型可以保證專業(yè)標(biāo)準(zhǔn)和成功的經(jīng)驗(yàn)?zāi)軌蛉谌腠?xiàng)目計(jì)劃。這類模型不僅可以保證質(zhì)量,還可以使重復(fù)勞動(dòng)降到最低程度。因此,當(dāng)遇到時(shí)間和預(yù)算壓力需要削減項(xiàng)目時(shí),項(xiàng)目經(jīng)理應(yīng)確定一種最佳的項(xiàng)目生命周期。

          5、所有項(xiàng)目目標(biāo)和項(xiàng)目活動(dòng)必須生動(dòng)形象地得以交流和溝通

          項(xiàng)目經(jīng)理和項(xiàng)目小組在項(xiàng)目開始時(shí)就應(yīng)當(dāng)形象化地描述項(xiàng)目的最終目標(biāo),以確保與項(xiàng)目有關(guān)的每一個(gè)人都能記住。項(xiàng)目成本的各個(gè)細(xì)節(jié)都應(yīng)當(dāng)清楚、明確、毫不含糊,并確保每個(gè)人對(duì)此都達(dá)成了一致的意見。

          6、采用漸進(jìn)的方式逐步實(shí)現(xiàn)目標(biāo)

          如果試圖同時(shí)完成所有的項(xiàng)目目標(biāo),只會(huì)造成重復(fù)勞動(dòng),既浪費(fèi)時(shí)間又浪費(fèi)錢。俗話說,一口吃不成個(gè)胖子。項(xiàng)目目標(biāo)只能一點(diǎn)一點(diǎn)地去實(shí)現(xiàn),并且每實(shí)現(xiàn)一個(gè)目標(biāo)就進(jìn)行一次評(píng)估,確保整個(gè)項(xiàng)目能得以控制。

          7、項(xiàng)目應(yīng)得到明確的許可,并由投資方簽字實(shí)施

          在實(shí)現(xiàn)項(xiàng)目目標(biāo)的過程中獲得明確的許可是非常重要的。應(yīng)將投資方的簽字批準(zhǔn)視為項(xiàng)目的一個(gè)出發(fā)點(diǎn)。道理很簡(jiǎn)單:任何有權(quán)拒絕或有權(quán)修改項(xiàng)目目標(biāo)的人都應(yīng)當(dāng)在項(xiàng)目啟動(dòng)時(shí)審查和批準(zhǔn)這些項(xiàng)目目標(biāo)。

          8、要想獲得項(xiàng)目成功必須對(duì)項(xiàng)目目標(biāo)進(jìn)行透徹的分析

          研究表明,如果按照眾所周知記錄在案的業(yè)務(wù)需求來設(shè)計(jì)項(xiàng)目的目標(biāo),則該項(xiàng)目多半會(huì)成功。所以,項(xiàng)目經(jīng)理應(yīng)當(dāng)堅(jiān)持這樣一個(gè)原則,即在組織機(jī)構(gòu)啟動(dòng)項(xiàng)目之前,就應(yīng)當(dāng)為該項(xiàng)目在業(yè)務(wù)需求中找到充分的依據(jù)。

          9、項(xiàng)目經(jīng)理應(yīng)當(dāng)責(zé)權(quán)對(duì)等

          項(xiàng)目經(jīng)理應(yīng)當(dāng)對(duì)項(xiàng)目的結(jié)果負(fù)責(zé),這一點(diǎn)并不過分。但與此相對(duì)應(yīng),項(xiàng)目經(jīng)理也應(yīng)被授予足夠的權(quán)利以承擔(dān)相應(yīng)的責(zé)任。在某些時(shí)候,權(quán)利顯得特別重要,如獲取或協(xié)調(diào)資源,要求得到有關(guān)的中小企業(yè)的配合,做相應(yīng)的對(duì)項(xiàng)目成功有價(jià)值的決策等等。

          10、項(xiàng)目投資方和用戶應(yīng)當(dāng)主動(dòng)介入,不能被動(dòng)地坐享其成

          多數(shù)項(xiàng)目投資方和用戶都能正確地要求和行使批準(zhǔn)(全部或部分)項(xiàng)目目標(biāo)的權(quán)力。但伴隨這個(gè)權(quán)力的是相應(yīng)的責(zé)任——主動(dòng)地介入項(xiàng)目的各個(gè)階段。例如,在項(xiàng)目早期要幫助確定項(xiàng)目目標(biāo);在項(xiàng)目進(jìn)行中,要對(duì)完成的階段性目標(biāo)進(jìn)行評(píng)估,以確保項(xiàng)目能順利進(jìn)行。項(xiàng)目投資方應(yīng)幫助項(xiàng)目經(jīng)理去訪問有關(guān)的中小企業(yè)和目標(biāo)顧客的成員,并幫助項(xiàng)目經(jīng)理獲得必要的文件資料。

          11、項(xiàng)目的實(shí)施應(yīng)當(dāng)采用市場(chǎng)運(yùn)作機(jī)制

          在多數(shù)情況下,項(xiàng)目經(jīng)理應(yīng)將自己看成是賣主,以督促自己完成投資方和用戶交付的任務(wù)。項(xiàng)目計(jì)劃一旦批準(zhǔn)項(xiàng)目經(jīng)理應(yīng)當(dāng)定期提醒項(xiàng)目小組成員該項(xiàng)目必須滿足的業(yè)務(wù)需求是什么,以及該怎樣工作才能滿足這些業(yè)務(wù)需求。

          12、項(xiàng)目經(jīng)理應(yīng)當(dāng)獲得項(xiàng)目小組成員的最佳人選

          最佳人選是指受過相應(yīng)的技能培訓(xùn),有經(jīng)驗(yàn),素質(zhì)高。對(duì)于項(xiàng)目來說,獲得最佳人選往往能彌補(bǔ)時(shí)間、經(jīng)費(fèi)或其它方面的不足。項(xiàng)目經(jīng)理應(yīng)當(dāng)為這些最佳的項(xiàng)目成員創(chuàng)造良好的工作環(huán)境,如幫助他們免受外部干擾,幫助他們獲得必要的工具和條件以發(fā)揮他們的才能。

          posted @ 2008-06-15 15:43 JavaSuns 閱讀(351) | 評(píng)論 (0)編輯 收藏

          什么是“成功項(xiàng)目”:談?wù)勡浖膬r(jià)值(看)

          在開始正文之前,我想先講兩個(gè)故事——關(guān)于軟件項(xiàng)目的故事。


          故事一

          有兩個(gè)軟件項(xiàng)目(姑且稱之為“項(xiàng)目 A”和“項(xiàng)目 B”),它們?cè)陂_始時(shí)的預(yù)算都是 50 個(gè)人月,時(shí)間是 5 個(gè)月。

          項(xiàng)目 A 在 5 個(gè)月后完工,耗費(fèi)成本 50 人月
          項(xiàng)目 B 在 6 個(gè)月后完工,耗費(fèi)成本 70 人月
          在軟件圈子里摸爬滾打多年的讀者們對(duì)這個(gè)故事一定有自己的判斷——而且我可以大致猜出是什么樣的判斷。不過先別著急,我們還有另一個(gè)故事。

          故事二

          有兩個(gè)軟件項(xiàng)目(仍然姑且稱之為“項(xiàng)目 A”和“項(xiàng)目 B”),它們?cè)陂_始時(shí)的計(jì)劃都是交付 200 項(xiàng)功能。

          項(xiàng)目 A 在項(xiàng)目結(jié)束時(shí)一次性交付了最初計(jì)劃的 200 項(xiàng)功能,但客戶發(fā)現(xiàn)其中大約 30 項(xiàng)功能沒有太大用處,而另外 30 項(xiàng)有用的功能要等到下一個(gè)項(xiàng)目才能實(shí)現(xiàn)。
          項(xiàng)目 B 在第一個(gè)月結(jié)束時(shí)交付了第一個(gè)版本,此后每?jī)芍芙桓兑粋€(gè)新的版本。在項(xiàng)目進(jìn)行的過程中,客戶進(jìn)行了一次業(yè)務(wù)調(diào)整,加入了 90 項(xiàng)新的功能,并擱置了 50 項(xiàng)用處不大的功能。最終該項(xiàng)目交付了 240 項(xiàng)功能。
          聰明的讀者大概注意到了,前后兩個(gè)故事講的是同一回事,同樣的兩個(gè)項(xiàng)目?,F(xiàn)在我的問題來了:請(qǐng)問哪個(gè)項(xiàng)目是更成功的項(xiàng)目?

          這個(gè)問題并不容易回答——實(shí)際上它沒有標(biāo)準(zhǔn)答案。站在很多軟件企業(yè)的立場(chǎng)上,項(xiàng)目 A 是一個(gè)理想的成功項(xiàng)目:按時(shí)間、按成本完成預(yù)先約定的任務(wù)。請(qǐng)注意,我用了“理想的”這個(gè)詞,稍后我還會(huì)解釋這個(gè)有趣的詞,因?yàn)閷?shí)際上的軟件項(xiàng)目往往沒有那么理想。

          而如果換一個(gè)角度,站在客戶的立場(chǎng)上呢?也許付錢購(gòu)買軟件的客戶會(huì)有一些不同的想法。項(xiàng)目 B 從開始之后一個(gè)月便交付了第一個(gè)可工作的版本,從那時(shí)起客戶就開始使用這個(gè)軟件的部分功能,并且不斷地把自己使用的感受反饋給開發(fā)團(tuán)隊(duì)。在真實(shí)的業(yè)務(wù)運(yùn)營(yíng)過程中,客戶甚至發(fā)現(xiàn)了一種新的盈利模式,并進(jìn)行了一次大規(guī)模的業(yè)務(wù)調(diào)整,這次調(diào)整的結(jié)果也直觀地體現(xiàn)在軟件項(xiàng)目中。雖然項(xiàng)目B的整體交付速率低于項(xiàng)目 A,但它提供的所有功能都是客戶真正需要的,它們?yōu)榭蛻籼峁?shí)實(shí)在在的價(jià)值——更不用說,客戶提前好幾個(gè)月就開始使用這個(gè)軟件。

          實(shí)際上,這是一篇關(guān)于軟件價(jià)值的文章。和“成功項(xiàng)目”一樣,對(duì)于“軟件的價(jià)值”,不同的人也會(huì)有不同的定義。不過作為付錢購(gòu)買軟件的客戶,他對(duì)于軟件價(jià)值的定義是一目了然的:他能夠從使用軟件中創(chuàng)造多少價(jià)值,軟件能夠?yàn)樗臉I(yè)務(wù)提供多少價(jià)值,這就是軟件的價(jià)值。或者說得更簡(jiǎn)明一點(diǎn):

          軟件價(jià)值源自使用
          這正是為什么很多客戶青睞“項(xiàng)目 B”的原因——我并不打算聲稱所有客戶都有同樣的觀點(diǎn),稍后我也會(huì)舉出反例,但至少支持這一觀點(diǎn)的客戶不在少數(shù)。因?yàn)樗麄兲幵谝粋€(gè)殘酷而快速變化的商業(yè)環(huán)境中:他們的供應(yīng)商在變化,他們的客戶在變化,他們所處的經(jīng)濟(jì)環(huán)境和政策環(huán)境也在變化。這一切的變化迫使他們的業(yè)務(wù)也要隨之變化。更要命的是,今天這個(gè)經(jīng)濟(jì)全球化的時(shí)代是一個(gè)“快魚吃慢魚”的時(shí)代,客戶迫切希望新的軟件系統(tǒng)為他們帶來競(jìng)爭(zhēng)優(yōu)勢(shì)——哪怕這個(gè)軟件系統(tǒng)尚未完成,只要能夠投入使用。最后,客戶對(duì)于新的軟件系統(tǒng)究竟應(yīng)該是什么樣子并沒有百分之百的把握,他們的想法往往要在真正使用軟件之后才會(huì)浮現(xiàn)成型。幾方面的因素加在一起,使得這些客戶更愿意盡快開始使用軟件、提出反饋、并不斷完善軟件,而不是提出一組需求、然后坐等幾個(gè)月之后原封不動(dòng)地拿到這些功能。

          一個(gè)真實(shí)的案例

          在 ThoughtWorks 的一個(gè)項(xiàng)目中,開發(fā)者們?cè)陧?xiàng)目開始之后一個(gè)月內(nèi)就發(fā)布了第一個(gè)版本——只有一些簡(jiǎn)單的數(shù)據(jù)采集功能。在發(fā)布展示會(huì)上,發(fā)生了這樣的對(duì)話……

          開發(fā)者:這是我們的第一個(gè)功能。我們從文本文件、Excel 數(shù)據(jù)表和遺留數(shù)據(jù)庫(kù)采集數(shù)據(jù),現(xiàn)在我們的數(shù)據(jù)庫(kù)中有這些數(shù)據(jù)……(展示數(shù)據(jù)庫(kù)結(jié)構(gòu))
          客戶:唔……有意思。要是你能做這樣一個(gè)查詢(寫出查詢要求),得到的結(jié)果可能會(huì)有用。
          開發(fā)者:可是我們的界面上沒有地方做這樣的查詢操作。
          客戶:啊,我不需要操作界面,只要每天深夜做一次查詢,把報(bào)表發(fā)到我的信箱就可以了。
          開發(fā)者:這樣嗎……另一個(gè)問題是,這需要花我們幾天時(shí)間。
          客戶:不要緊,把別的任務(wù)往后放幾天好了,我很想看到這份報(bào)表。
          開發(fā)者:那好吧,下周我們就會(huì)開始提供這個(gè)報(bào)表。
          猜猜結(jié)果怎么樣?一周之后客戶就開始每天接收這份報(bào)表,并根據(jù)報(bào)表內(nèi)容做一些分析和決策。僅僅幾個(gè)月之后,這份報(bào)表給客戶帶來的收益就已經(jīng)超過了整個(gè)項(xiàng)目的投資——這時(shí)項(xiàng)目其他部分的開發(fā)甚至還沒有完成。

          想想這個(gè)客戶會(huì)怎么定義一個(gè)“成功的軟件項(xiàng)目”?好吧,也許這個(gè)項(xiàng)目超過了預(yù)期的時(shí)間,也許投入了更多的人力,但這些并不意味著“項(xiàng)目失敗”——只是付出更高的成本。關(guān)鍵在于,他投入的這些成本能夠帶來多大的收益,他的投資回報(bào)率是否劃算。對(duì)于這個(gè)客戶而言,如果項(xiàng)目能夠隨時(shí)給他提供可用的、能夠創(chuàng)造最大價(jià)值的軟件,能夠隨時(shí)讓——就像故事中提到的——這種有價(jià)值的想法得以實(shí)現(xiàn),這就是一個(gè)成功的項(xiàng)目。

          所以,親愛的讀者,請(qǐng)你忘記本文標(biāo)題上出現(xiàn)的“敏捷”二字,我們?cè)谶@里所說的不是別的,就是一種為客戶創(chuàng)造最大化價(jià)值的軟件開發(fā)方法。這樣的方法有很多種,但它們有一個(gè)共同的特點(diǎn):盡快、盡可能頻繁地交付可以工作的軟件,讓客戶盡快開始使用軟件,從使用中創(chuàng)造價(jià)值、厘清思路、提出反饋。仍然以 ThoughtWorks 的項(xiàng)目為例,這些項(xiàng)目通常在啟動(dòng)開發(fā)階段之后一個(gè)月內(nèi)就會(huì)發(fā)布第一個(gè)版本,隨后每一周或每?jī)芍馨l(fā)布一個(gè)新版本——每個(gè)版本都是一個(gè)可以工作的軟件,每個(gè)版本都比前一個(gè)版本具有更豐富的功能,并且每個(gè)版本都包含客戶認(rèn)為迄今為止最有價(jià)值的那些功能。用軟件開發(fā)的“黑話”,“開發(fā)下一個(gè)版本”的過程叫做“迭代”,這些開發(fā)方法最大的共同點(diǎn)就是“迭代式開發(fā)”——不是一股腦地交付全部功能,而是每次增加一點(diǎn)、漸進(jìn)地交付最有價(jià)值的功能。

          軟件開發(fā)的夢(mèng)想與真實(shí)

          回到文章開始處的兩個(gè)故事。我曾經(jīng)說過,對(duì)于很多軟件企業(yè)而言,項(xiàng)目 A 是一個(gè)“理想的”成功項(xiàng)目。那么,是什么讓情況變得不那么理想?

          答案是一個(gè)所有軟件開發(fā)者耳熟能詳?shù)脑~:需求變更。在真實(shí)的項(xiàng)目中,客戶通常不會(huì)等到最后一天再照單全收整個(gè)項(xiàng)目,因?yàn)樗雷约旱臉I(yè)務(wù)正在發(fā)生變化。這時(shí)需求變更就出現(xiàn)了,伴隨著來回的扯皮和討價(jià)還價(jià)。更糟的是,大量的需求變更發(fā)生在項(xiàng)目晚期——因?yàn)橹钡竭@時(shí)客戶才真正看到、使用到這個(gè)軟件,他的很多想法才真正浮現(xiàn)成型。隨著這種“最后一分鐘的需求變更”,項(xiàng)目超期、超出預(yù)算也就成了家常便飯。能夠像項(xiàng)目A這樣完工交付的,實(shí)在是鳳毛麟角的幸運(yùn)兒。

          為了對(duì)付需求變更這個(gè)噩夢(mèng),軟件開發(fā)者們還發(fā)明了另一個(gè)詞:變更控制。這個(gè)有趣的詞暗示著:需求變更是一種“不好”的東西,是需要“控制”的東西。然而站在客戶的角度上想想,他在親身使用了軟件之后提出的要求,難道不是最有價(jià)值的東西嗎?把這種真正創(chuàng)造業(yè)務(wù)價(jià)值的要求“控制”起來,難道是合理的嗎?

          在前面我也暗示過,并非所有的客戶都一定青睞迭代式開發(fā)。那么,哪些軟件項(xiàng)目不一定需要迭代式開發(fā)呢?從整篇文章的內(nèi)容不難看出,如果客戶的業(yè)務(wù)絕對(duì)不會(huì)變化,如果客戶的需求巨細(xì)靡遺非常明確,如果客戶不需要盡快開始使用軟件以便收回成本,那么迭代式開發(fā)對(duì)他的幫助就會(huì)小得多。不過,如果讀者認(rèn)真思考的話,這樣的例子也許并不多——也許比你最初認(rèn)為的要少得多。一個(gè)很好的例子是“神州六號(hào)”火箭使用的計(jì)算機(jī)控制系統(tǒng)。還有多少這樣的例子?讀者不妨試著自己想想。

          如果我足夠幸運(yùn)的話,也許一些讀者已經(jīng)被這篇文章吊起了胃口:既然有這么好的軟件開發(fā)方法,既然它能夠?yàn)槲覀儎?chuàng)造更大的價(jià)值,那還等什么呢,我們馬上就動(dòng)手吧。事情不會(huì)那么簡(jiǎn)單。為了讓迭代式開發(fā)能夠成為現(xiàn)實(shí),為了確保盡快、盡可能頻繁地交付,為了確保每次交付的都是最有價(jià)值的功能,我們——包括軟件開發(fā)者、軟件企業(yè)和客戶——需要很多的改變。這里既有職責(zé)與權(quán)利的劃分,也有開發(fā)過程和團(tuán)隊(duì)的重組,還有技術(shù)層面的實(shí)踐指導(dǎo)。這些正是敏捷方法學(xué)所涵蓋的內(nèi)容。缺少了這些東西,“為客戶創(chuàng)造最大價(jià)值”就只能成為一句空話。在后續(xù)的文章里,我們將結(jié)合 ThoughtWorks 的實(shí)踐經(jīng)驗(yàn),逐步介紹敏捷方法的方方面面。

           

          posted @ 2008-06-15 15:35 JavaSuns 閱讀(312) | 評(píng)論 (0)編輯 收藏

          java與C#區(qū)別(轉(zhuǎn))

          最開始時(shí)微軟公司將Java當(dāng)做一種能解決C和C++中存在的問題的語言,并不在意,并繼續(xù)維持和培訓(xùn)著其C和C++技術(shù)和編程人員。接下來不幸的是,正當(dāng)微軟盡力在Visual J++基礎(chǔ)上拓展Java功能,并使之與Windows操作系統(tǒng)緊密結(jié)合在一起的時(shí)候,Sun公司對(duì)微軟提出法律訴訟說其違反了許可證協(xié)議中的條款,最終的結(jié)果是微軟公司不得不停止其Visual J++產(chǎn)品的開發(fā)。(微軟公司仍然銷售Visual J++,但是從1998年10月以來就沒有新的版本發(fā)布,并且在.Net平臺(tái)上也沒有Visual J++的位置了)接下來的事情就很清楚了,微軟公司開發(fā)了C#語言。接下來的一部分將討論C#與Java的相似性。
            C#與Java的區(qū)別
            C#最引人的地方是它與Java的區(qū)別而不是其相似性。下面主要來介紹C#區(qū)別于Java的不同的運(yùn)行特點(diǎn)及Java完全沒有的特點(diǎn)。
            中間語言
            當(dāng)MSIL被編譯成最終的機(jī)器碼時(shí),微軟公司在如何選擇上是非常靈活的。微軟公司很謹(jǐn)慎的對(duì)外宣稱說MSIL不是解釋型的,而是被編譯成機(jī)器碼。因?yàn)殚_發(fā)人員都有這樣一個(gè)觀念:Java程序天生就比C程序運(yùn)行慢,所以這暗示著基于MSIL的程序優(yōu)于解釋型的Java字節(jié)碼。當(dāng)然,既然C#和其它MSIL產(chǎn)品編譯器還未發(fā)布,那么這一點(diǎn)就還未證明,但是Java無處不在的即時(shí)編譯器使得C#和Java在效能上是一樣的。象“C#是編譯型的,Java是解釋型的”這樣話只是銷售中的技巧。Java的字節(jié)碼和MSIL碼都是的類似匯編的中間語言,在運(yùn)行時(shí)執(zhí)行這些中間碼。
            與COM的整合
            對(duì)于基于Windows的C#開發(fā)人員來說,最大的收獲是對(duì)COM的無損整合,COM是微軟Win32的組件技術(shù)。實(shí)際上,任何一種.Net體系結(jié)構(gòu)上的語言最終都可能去寫COM的客戶端和服務(wù)器端程序。用C#編寫的類也會(huì)作為COM組件的子類;結(jié)果類(resulting class)也能作為COM組件使用,并作為COM組件的子類。
            微軟公司的目標(biāo)是使越來越多的語言都能訪問組件,并使這些組件能整合到.Net體系結(jié)構(gòu)中。已有幾個(gè)廠商開始著手開發(fā)支持.Net功能的編程語言,如COBOL和Haskell。開發(fā)人員能選擇不同的語言解決不同問題,更重要的是,開發(fā)人員不必為采用.Net體系結(jié)構(gòu)而必須學(xué)習(xí)新語言,可以選擇一種他們熟悉的語言。

            總結(jié)
            本文的第一、二部分對(duì)C#做了一膚淺的總體介紹,主要是其產(chǎn)生動(dòng)機(jī)及與Java的相似性。第三部分則涵概了C#的語言特點(diǎn)。用范例說明了C#與Java兩者在相似性外,它們又是非常不同的,有許多細(xì)微的語義和設(shè)計(jì)區(qū)別,適合不同的技術(shù)和市場(chǎng)環(huán)境,又談到了微軟公司對(duì)C#進(jìn)行標(biāo)準(zhǔn)化方面的嘗試,及其對(duì)Java的影響。
          c#與java的區(qū)別

          1.屬性:
          java中定義和訪問均要用get和set方法,可以不成對(duì)出現(xiàn)。
          c#中是真正的屬性,定義時(shí)get和set必須同時(shí)出現(xiàn),房問時(shí)用.號(hào)即可。不用get,set

          2.對(duì)象索引
          就是對(duì)象數(shù)組
          public Story this [int index] {

          3.C#中,不用任何范圍修飾符時(shí),默認(rèn)的是protect,因而不能在類外被訪問.

          4.因?yàn)镴AVA規(guī)定,在一個(gè)文件中只能有一個(gè)public類,而且這個(gè)類的名稱必須與文件名一模一樣,這是一個(gè)區(qū)別

          5.在C#中,它是以Main方法來定位入口的.如果一個(gè)程序中沒有一個(gè)名為Main的方法,就會(huì)出"找不到入口的錯(cuò)誤".不要把Main寫成main喲

          6.C#預(yù)定義的簡(jiǎn)單數(shù)據(jù)類型比Java多。例如,C#有unit,即無符號(hào)整數(shù)

          7.忘掉Java中的static final修飾符。在C#中,常量可以用const關(guān)鍵詞聲明
          C#的設(shè)計(jì)者還增加了readonly關(guān)鍵詞,readonly域只能通過初始化器或類的構(gòu)造函數(shù)設(shè)置
          8.公用類的入口點(diǎn):c#是可以對(duì)Main進(jìn)行重載(java中是main),允許有int返回值和空參數(shù)的Main

          9.在Java中,switch語句只能處理整數(shù)。但C#中的switch語句不同,它還能夠處理字符變量。請(qǐng)考慮下面用switch語句處理字符串變量的C#代碼

          10.C#沒有>>>移位操作符

          11.goto關(guān)鍵詞:
          Java不用goto關(guān)鍵詞。在C#中,goto允許你轉(zhuǎn)到指定的標(biāo)簽。不過,C#以特別謹(jǐn)慎的態(tài)度對(duì)待goto,比如它不允許goto轉(zhuǎn)入到語句塊的內(nèi)部。在Java中,你可以用帶標(biāo)簽的語句加上break或continue取代C#中的goto。

          12.int[] x = { 0, 1, 2, 3 };
          int x[] = { 0, 1, 2, 3 };
          但在C#中,只有第一行代碼合法,[]不能放到變量名字之后。

          13.與Java不同的是,C#允許為名稱空間或者名稱空間中的類指定別名:
          using TheConsole = System.Console;

          14.在Java中,包的名字同時(shí)也是實(shí)際存在的實(shí)體,它決定了放置.java文件的目錄結(jié)構(gòu)。在C#中,物理的包和邏輯的名稱之間是完全分離的
          .NET中包的實(shí)體稱為程序集(Assembly)。每一個(gè)程序集包含一個(gè)manifest結(jié)構(gòu)。manifest列舉程序集所包含的文件,控制哪些類型和資源被顯露到程序集之外,并把對(duì)這些類型和資源的引用映射到包含這些類型與資源的文件。程序集是自包含的,一個(gè)程序集可以放置到單一的文件之內(nèi),也可以分割成多個(gè)文件。.NET的這種封裝機(jī)制解決了DLL文件所面臨的問題,即臭名昭著的DLL Hell問題。

          15.在Java中,java.lang包是默認(rèn)的包,C#中不存在默認(rèn)的包

          16.C#中的訪問修飾符與Java中的基本對(duì)應(yīng),但多出了一個(gè)internal。簡(jiǎn)而言之,C#有5種類型的可訪問性,如下所示:

          public:成員可以從任何代碼訪問。
          protected:成員只能從派生類訪問。
          internal:成員只能從同一程序集的內(nèi)部訪問。
          protected internal:成員只能從同一程序集內(nèi)的派生類訪問。
          private:成員只能在當(dāng)前類的內(nèi)部訪問。

          17.由于C#中不存在final關(guān)鍵詞,如果想要某個(gè)類不再被派生,你可以使用sealed關(guān)鍵詞

          18.與Java不同,C#中的接口不能包含域(Field)。
          另外還要注意,在C#中,接口內(nèi)的所有方法默認(rèn)都是公用方法。在Java中,方法聲明可以帶有public修飾符(即使這并非必要),但在C#中,顯式為接口的方法指定public修飾符是非法的。例如,下面的C#接口將產(chǎn)生一個(gè)編譯錯(cuò)誤。

          19.C#中的is操作符與Java中的instanceof操作符一樣,兩者都可以用來測(cè)試某個(gè)對(duì)象的實(shí)例是否屬于特定的類型。在Java中沒有與C#中的as操作符等價(jià)的操作符。as操作符與is操作符非常相似,但它更富有“進(jìn)取心”:如果類型正確的話,as操作符會(huì)嘗試把被測(cè)試的對(duì)象引用轉(zhuǎn)換成目標(biāo)類型;否則,它把變量引用設(shè)置成null。

          20.C#仍舊保留了C++的內(nèi)存手工管理方法,它適合在速度極端重要的場(chǎng)合使用,而在Java中這是不允許的

          21.在C#中,所有的異常都從一個(gè)名為Exception的類派生

          22.枚舉器即enum類型(java無),把它作為一個(gè)變量值的類型使用,從而把變量可能的取值范圍限制為枚舉器中出現(xiàn)的值。

          23.結(jié)構(gòu)(Struct)與類很相似,而結(jié)構(gòu)是一種值類型,它存儲(chǔ)在棧中或者是嵌入式的,結(jié)構(gòu)可以實(shí)現(xiàn)接口,可以象類一樣擁有成員,但結(jié)構(gòu)不支持繼承

          24.屬性聲明語法的第一部分與域聲明很相似,第二部分包括一個(gè)set過程和/或一個(gè)get過程

          25.傳值方式:
          在java中簡(jiǎn)單數(shù)據(jù)類型的值傳參時(shí),都以傳值方式;
          在c#中如果加ref則會(huì)以引用的方式傳值(方法內(nèi)部改變?cè)搮?shù),則外部變量一起跟著變);
          加out與ref基本相同,但out不要求參數(shù)一定要初始化.

          26.c#保留了指針。unsafe

          27.代理:代理(delegate)可以看作C++或者其他語言中的函數(shù)指針
          代理用來封裝可調(diào)用方法。你可以在類里面編寫方法并在該方法上創(chuàng)建代理,此后這個(gè)代理就可以被傳遞到第二個(gè)方法。這樣,第二個(gè)方法就可以調(diào)用第一個(gè)方法。
          代理是從公共基類System.Delegate派生的引用類型。定義和使用代理包括三個(gè)步驟:聲明,創(chuàng)建實(shí)例,調(diào)用。代理用delegate聲明語法聲明。

          posted @ 2008-06-15 14:37 JavaSuns 閱讀(918) | 評(píng)論 (0)編輯 收藏

          僅列出標(biāo)題
          共5頁(yè): 1 2 3 4 5 下一頁(yè) 
          主站蜘蛛池模板: 从江县| 杭州市| 张家港市| 宜宾市| 班戈县| 湘乡市| 高邑县| 微山县| 卢湾区| 北碚区| 鄯善县| 伊川县| 和平县| 万年县| 云安县| 永宁县| 个旧市| 大足县| 高要市| 明光市| 丰原市| 外汇| 福贡县| 文水县| 芷江| 电白县| 惠州市| 盖州市| 宁都县| 哈巴河县| 宁安市| 新竹县| 辉南县| 华亭县| 南部县| 江孜县| 乐清市| 伊宁市| 渭南市| 宜阳县| 九江市|