Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Friday, January 15, 2016

[Java] Copy dữ liệu sang file khác trong Java

Bài viết sẽ trình bày cách copy dữ liệu từ một file sang một file khác trong Java. Theo thứ tự để copy dữ liệu sang file khác, ta cần phải đọc dữ liệu (sử dụng FileInputStream) và viết dữ liệu sang file khác (sử dụng FileOutputStream).
Chương trình sau sẽ copy dữ liệu từ file "MyInputFile.txt" sang file "MyOutputFile.txt". Nếu file "MyOutputFile.txt" chưa tồn tại thì chương trình sẽ tạo file và copy dữ liệu sang file đó.
package simplecodecjava.blogspot.com;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyExample {
 public static void main(String[] args) {
  FileInputStream instream = null;
  FileOutputStream outstream = null;

  try {
   File infile = new File("src/simplecodecjava/blogspot/com/MyInputFile.txt");
   File outfile = new File("src/simplecodecjava/blogspot/com/MyOutputFile.txt");

   instream = new FileInputStream(infile);
   outstream = new FileOutputStream(outfile);

   byte[] buffer = new byte[1024];

   int length;
   /*
    * copy dữ liệu từ file đầu vào sang file đầu ra
    *  sử dụng phương thức read và write trong java.
    */
   while ((length = instream.read(buffer)) > 0) {
    outstream.write(buffer, 0, length);
   }
   /*Đóng luồng input/output*/
   instream.close();
   outstream.close();
   System.out.println("Copy thành công!");
  } catch (IOException ioe) {
   ioe.printStackTrace();
  }
 }
}
Output
Copy thành công!
Chương trình trên sử dụng phương thức read để đọc dữ liệu.
public int read(byte[] b) throws IOException
Khi gọi phương thức trên chương trình sẽ đọc vào mảng buffer 1024 (kích thước của mảng đệm buffer) byte từ luồng dữ liệu đầu vào instream . Phương thức này sẽ trả về số tổng số file được đọc vào mảng buffer. Nếu file không chứa dữ hiệu hoặc chương trình đã đọc đến đoạn kết thúc của file phương thức read sẽ trả về -1.

Chương trình trên sử dụng phương thức write để ghi dữ liệu.
public void write(byte[] b,int off, int length) throws IOException
Phương thức trên sẽ viết length byte từ mảng b bắt đầu từ vị trí off ra file đầu ra.

Saturday, January 9, 2016

[Java] Lấy IP trong Java

Bài viết sẽ hướng dẫn bạn lấy địa chỉ IP từ hệ thống. Các bước để lấy địa chỉ IP như sau:
1. Lấy địa chỉ local host bằng phương thức getLocalHost() của class InetAddress.
2. Lấy địa chỉ IP bằng phương thức getHostAddress().
Chương trình cài đặt.
package simplecodecjava.blogspot.com;

import java.net.InetAddress;

public class GetIPAddress {
 public static void main(String[]args) throws Exception{
  /*phhương thức static InetAddress getLocalHost() ném ra UnknownHostException,
  Phương thức này trả về địa chỉ của local host.*/
  InetAddress myIP = InetAddress.getLocalHost();
  System.out.print("Địa chỉ IP của máy tính là: ");
  System.out.print(myIP.getHostAddress());
  
 }
}

Output:
Địa chỉ IP của máy tính là: 107.113.187.26

Thursday, January 7, 2016

[Java] Chuyển từ hệ thập phân sang hệ nhị phân.

Có 3 cách để chuyển một số từ hệ thập phân sang hệ nhị phân.
  1. Sử dụng phương thức toBinaryString() trong class Integer của Java.
  2. Sử dụng phương thức chuyển đổi bằng logic mà không sử dụng phương thức có sẵn của Java.
  3. Sử dụng Stack.
1. Sử dụng phương thức toBinaryString().
package simplecodecjava.blogspot.com;

public class DecimalToBinaryExample {
 public static void main(String[]args){
  int decimalNumber = 123456789;
  System.out.print("Hệ nhị phân của " + decimalNumber +" là :");
  System.out.print(Integer.toBinaryString(decimalNumber));
 }
}
Output:
Hệ nhị phân của 123456789là :111010110111100110100010101
2. Sử dụng chuyển đổi bằng logic.
package simplecodecjava.blogspot.com;

public class DecimalToBinaryExample {
 
 public void convertBinary(int num){
      int binary[] = new int[40];
      int index = 0;
      while(num > 0){
        binary[index++] = num%2;
        num = num/2;
      }
      for(int i = index-1;i >= 0;i--){
        System.out.print(binary[i]);
      }
   }
  
 public static void main(String[]args){
  int decimalNumber = 123456789;
  System.out.print("Hệ nhị phân của " + decimalNumber +" là :");
  new DecimalToBinaryExample().convertBinary(decimalNumber);
 }
}
Output:
Hệ nhị phân của 123456789 là :111010110111100110100010101
3. Sử dụng Stack.
package simplecodecjava.blogspot.com;

import java.util.Stack;

public class DecimalToBinaryExample {
 
 public void convertBinary(int num){
  Stack<Integer> stack = new Stack<Integer>();
     while(num != 0){
      //thực hiện phép chia lấy phần dư cho 2.
      int d = num%2;
      // thêm vào stack.
      stack.push(d);
      num/=2;
     }
     while(!(stack.isEmpty())){
      System.out.print(stack.pop());
     }
     
   }
  
 public static void main(String[]args){
  int decimalNumber = 123456789;
  System.out.print("Hệ nhị phân của " + decimalNumber +" là :");
  new DecimalToBinaryExample().convertBinary(decimalNumber);
 }
}
Output:
Hệ nhị phân của 123456789 là :111010110111100110100010101

Wednesday, January 6, 2016

[Java] Sự khác nhau giữa HashMap và Hashtable

Sự khác nhau giữa HashMap HashTable ? Đây là câu hỏi thường được đưa ra trong các cuộc phỏng vấn chuyên gia Java/J2EE.
HashMapHashTable đều được implements từ java.util.Map interface. Tuy nhiên có một vài sự khác biệt giữa chúng trong cách thức hoạt động và sử dụng.
HashMap vs HashTable.
1. Khả năng đồng bộ.
- HashMap là lớp không đồng bộ (non-synchronized). Điều đó có nghĩa là HashMap có thể cho phép có nhiều hơn một thread cùng truy cập và sử lý dữ liệu và nó chứa đựng một cách đồng thời.
 void clear()
 Object clone()
 boolean containsKey(Object key)
 boolean containsValue(Object value)
 Set<Entry<K, V>> entrySet()
 V get(Object key)
 boolean isEmpty()
 Set<k> keySet()
 V put(K key, V value)
 void putAll(Map map)
 V remove(Object key)
 int size()
 Collection<v> values()

- HashTable là lớp đồng bộ (synchronized). Điều đó có nghĩa là HashTable chỉ cho phép tối đa một thread truy cập và xử lý dữ liệu tại một thời điểm. Thread này chiếm giữ HashTable và các Thread khác phải chờ cho đến khi Thread này truy cập và xử lý  xong.
 synchronized void clear()
 synchronized Object clone()
 boolean contains(Object value)
 synchronized boolean containsKey(Object key)
 synchronized boolean containsValue(Object value)
 synchronized Set<Entry<K, V>> entrySet()
 synchronized boolean equals(Object object)
 synchronized V get(Object key)
 synchronized int hashCode()
 synchronized boolean isEmpty()
 synchronized Set<k> keySet()
 synchronized Enumeration<k> keys()
 synchronized V put(K key, V value)
 synchronized void putAll(Map map)
 synchronized V remove(Object key)
 synchronized int size()
 synchronized String toString()
 synchronized Collection<v> values()


2. Khóa và Giá trị.
- HashMap cho phép lưu khóa và giá trị là NULL.
- HashTable không cho phép lưu khóa và giá trị là NULL.
package simplecodecjava.blogspot.com;

import java.util.HashMap;
import java.util.Hashtable;

public class HashMapvsHashTable {
 private HashMap<String, String> myHashMap = new HashMap<String, String>();
 private Hashtable<String, String> myHashTable = new Hashtable<String, String>();
 public HashMapvsHashTable() {
  try{
  myHashMap.put(null, null);
  myHashTable.put(null, null);
  }catch(Exception e){
   e.printStackTrace();
  }
 }
 public static void main(String[]args){
  new HashMapvsHashTable();
 }
}
Output
java.lang.NullPointerException
 at java.util.Hashtable.put(Unknown Source)
 at simplecodecjava.blogspot.com.HashMapvsHashTable.<init>(HashMapvsHashTable.java:12)
 at simplecodecjava.blogspot.com.HashMapvsHashTable.main(HashMapvsHashTable.java:18)

3. Chèn và ánh xạ.
- HashMap là cài đặt của LinkedHashMap TreeMap. Vì vậy mà khi các phần từ được chèn vào trong HashMap theo một thứ tự và sắp xếp sự ánh xạ theo thứ tự tăng dần của khóa.
- HashTable thì ngược lại. Tức các phần tử được chèn vào trong HashTable không theo một thứ tự và sự ánh xạ cũng không theo thứ tự tăng dần của khóa.
4. Thành phần của Java Collection Framework.
- HashMap là một thành phần của Java Collection Framework.
- HashTable là lớp được dùng lại từ thành phần Java cũ nên không thuộc Java Collection Framework.
//HashTable được định nghĩa như sau
public class Hashtable extends Dictionary implements Map, Cloneable, Serializable {}
//HashMap được định nghĩa như sau
public class HashMap extends AbstractMap implements Map, Cloneable, Serializable {}
5. Cải tiến
 HashMap khắc phục một vài thiếu sót của HashTable. HashTable có phương thức contains(Object value) sẻ trả về true nếu HashTale có chứa đối tượng value. Trong khi đó HashMap có hai phương thức: phương thức containsKey(Object key) trả về true nếu HashMap có chứa đối tượng khóa, phương thức containValue(Object value) trả về true nếu HashMap có chứa đối tượng giá trị.
Sử dụng HashMap và HashTable.
1. Như so sánh ở trên sự khác nhau quan trọng nhất của HashMap HashTable là khả năng đồng bộ. Khi muốn sự thực thi của các luồng diễn ra an toàn thì nên sử dụng HashTable.
2. Sự đồng bộ sẽ làm giảm hiệu năng của chương trình vì vậy việc đồng bộ các luồng (synchromized) nên được tránh trừ trường hợp thực sự cần thiết. Do đó trong trường chương trình có nhiều Thread không đọc và ghi dữ liệu đồng thời thì nên sử dụng HashMap.

Thursday, December 31, 2015

[Java] Tạo file trong Java

Bài viết này sẽ trình bày cách tạo một file trong Java bằng phương thức createNewFile(). Phương thức này sẽ tạo ra một file rỗng. Nếu folder của đường dẫn tạo file chưa có file thì phương thức sẽ trả về TRUE. Nếu folder của đường  dẫn tạo file đã có file tồn tại phương thức sẽ trả về FALSE. Phương thức creatNewFile() sẽ ném ra các exception sau:
- IOException - Nếu có lỗi xảy ra trong quá trình tạo file.
- SecurityException - Nếu tồn tại Security manager và phương thức SecurityManager.checkWrite(java.lang.String) không có quyền write vào file.
Chương trình cài đặt:
Chương trình sau sẽ tạo ra một file txt có tên là "newfile.txt" trong ổ C. Để tạo file ở một ổ đĩa bất kỳ chỉ cần thay thổi đường dẫn tạo file.
package simplecodecjava.blogspot.com;

import java.io.File;
import java.io.IOException;

public class CreateFileDemo {
 public static void main(String[] args) {
  try {
   File file = new File("C:\\newfile.txt");
   /*
    * Nếu trong ổ C chưa tồn tại file newfile.txt thì phương thức createNewFile() trả về true
    * Nếu file đã tồn tại thì phương thức createNewFile() trả về false.
    */
   boolean fvar = file.createNewFile();
   if (fvar) {
    System.out.println("File đã được tạo thành công");
   } else {
    System.out.println("File đã tồn tại");
   }
  } catch (IOException e) {
   System.out.println("Đã xảy ra lỗi:");
   e.printStackTrace();
  }
 }
}

Wednesday, December 30, 2015

[Java] Cắt String trong Java - Split String in Java.

Phương thức split() được sử dụng để cắt một String thành các String nhỏ dựa trên ký tự phân chia. Phương thức này có 2 biến thể.
*String[] split(String kytuphanchia): Kết quả trả về là một mảng string sau khi cắt input String đầu vào theo 'kytuphanchia'.
*String[] split(String kytuphanchia, int gioihan): Kết quả trả về là một mảng String có kích thước bằng gioihan. Ví dụ: split('kytuphanchia',3) sẽ trả về một mảng String có kích thước là 3 mặc dù String input đầu vào sau khi split theo 'kytuphanchia' có thể có kích thước lớn hơn 3. Khi gioihan là một số âm mảng array String trả về sẽ chứa tất cả các String có thể cắt được từ input String đầu vào. Khi goihan là 0 thì mảng array String trả về sẽ chứa không chứa ký tự string rỗng ở cuối. Nghe có vẻ khó hiểu nhưng bài viết sẽ phân tích về gioihan là số âm, gioihan bằng 0 ở ví dụ phía dưới.
Chương trình cài đặt:
package simplecodecjava.blogspot.com;

public class SplitExample {
 public static void main(String args[]) {
  String str = new String("28/12/2015/ /simplecodecjava.blogspot.com");
  System.out.println("split(String kytuphanchia):");
  String array1[] = str.split("/");
  for (String temp : array1) {
   System.out.println(temp);
  }
  System.out.println("split(String kytuphanchia, int gioihan) với gioihan=2:");
  String array2[] = str.split("/", 2);
  for (String temp : array2) {
   System.out.println(temp);
  }
  System.out.println("split(String kytuphanchia, int gioihan) với gioihan=0:");
  String array3[] = str.split("/", 0);
  for (String temp : array3) {
   System.out.println(temp);
  }
  System.out.println("split(String kytuphanchia, int gioihan) với gioihan=-5:");
  String array4[] = str.split("/", -5);
  for (String temp : array4) {
   System.out.println(temp);
  }
 }
}
Output:
split(String kytuphanchia):
28
12
2015
 
simplecodecjava.blogspot.com
split(String kytuphanchia, int gioihan) với gioihan=2:
28
12/2015/ /simplecodecjava.blogspot.com
split(String kytuphanchia, int gioihan) với gioihan=0:
28
12
2015
 
simplecodecjava.blogspot.com
split(String kytuphanchia, int gioihan) với gioihan=-5:
28
12
2015
 
simplecodecjava.blogspot.com
Kết quả của chương trình trên.
* Với trường hợp gioihan = 2 thì mảng String đầu ra có kích thước là 2. Do đó mà kết quả in ra {'28','12/2015/ /simplecodecjava.blogspot.com'}
* Với trường hợp gioihan = -5 và gioihan=0 cho cùng một kết quả {'28','12','2015','','simplecodecjava.blogspot.com'}
* Nếu thay input String đầu vào:
String str = new String("28/12/2015/ /simplecodecjava.blogspot.com//");
Ta sẽ thấy kết quả chương trình có sự khác biệt giữa gioihan=-5 và gioihan=0:
split(String kytuphanchia):
28
12
2015
 
simplecodecjava.blogspot.com
split(String kytuphanchia, int gioihan) với gioihan=2:
28
12/2015/ /simplecodecjava.blogspot.com//
split(String kytuphanchia, int gioihan) với gioihan=0:
28
12
2015
 
simplecodecjava.blogspot.com
split(String kytuphanchia, int gioihan) với gioihan=-5:
28
12
2015
 
simplecodecjava.blogspot.com


* gioihan = -5: input string đầu vào đã được cắt ra thành {'28','12','2015',' ','simplecodecjava.blogspot.com',' ',' '}.
* gioihan = 0: input string đầu vào đã được cắt ra thành {'28','12','2015',' ','simplecodecjava.blogspot.com'}.
Mảng string thu được sau khi cắt với gioihan = -5 so với gioihan = 0 nhiều hơn 2 string rỗng bởi 2 ký tự cuối {//} trong chuỗi input String đầu vào cũng bị cắt ra và tạo thành 2 String rỗng.

Chú ý:
*Khi kytuphanchia là những ký tự đặc biệt. thì cần phải thêm '\\' vào đằng  trước.
Phân chia theo dấu '.' được viết thành: string.split('\\.');
Phân chia theo dấu '^' được viết thành: string.split('\\^');
Phân chia theo khoảng trắng ' ' được viết thành: string.split('\\s');
Phân chia theo dấu '|' được viết thành: string.split('\\|');
* Khi muốn cắt String theo chữ số dùng '\\d+'
String str = new String("abc123def456ghj");
  System.out.println("split(String kytuphanchia):");
  String array1[] = str.split("\\d+");
  for (String temp : array1) {
   System.out.println(temp);
  }
Output:
split(String kytuphanchia):
abc
def
ghj

* Khi muốn cắt String theo chữ cái dùng '[a-zA-Z]+'
String str = new String("0abc123def456ghj");
  System.out.println("split(String kytuphanchia):");
  String array1[] = str.split("[a-zA-Z]+");
  for (String temp : array1) {
   System.out.println(temp);
  }
Output:
split(String kytuphanchia):
0
123
456

Tuesday, December 29, 2015

[Java] Enum trong Java

1. Enum
Enum là một kiểu dữ liệu đặc biệt, về cơ bản enum là một tập các hằng số.
Đây là một ví dụ về enum:
public enum Directions{
  EAST, 
  WEST, 
  NORTH, 
  SOUTH
}
Ở đây Directions là một kiểu enum, là một tập chứa 4 hằng số EAST, WEST, NORTH và SOUTH.
2. Gán giá trị cho kiểu enum.
Directions dir = Directions.NORTH;
Biến dir có kiểu là Direction, có thể nhận bất kỳ giá trị nào trong bốn giá trị (EAST, WEST, NORTH, SOUTH). Trong ví dụ trên dir nhận giá trị NORTH.
3. Sử dụng enum trong mệnh đề if-else.
Biến có kiểu enum có thể được dùng trong mệnh đề if-else.
public enum Directions{
   EAST, 
   WEST, 
   NORTH, 
   SOUTH
}
public class EnumDemo
{
   public static void main(String args[]){
 Directions dir = Directions.NORTH;  
 if(dir == Directions.EAST) {
     System.out.println("Direction: East");
 } else if(dir == Directions.WEST) {
     System.out.println("Direction: West");
   } else if(dir == Directions.NORTH) {
       System.out.println("Direction: North");
       } else {
  System.out.println("Direction: South");
       }
   }
}
Output:
Direction: North
4. Sử dụng enum trong mệnh đề Swich-Case
public enum Directions{
   EAST, 
   WEST, 
   NORTH, 
   SOUTH
}
public class EnumDemo
{
   Directions dir;
   public EnumDemo(Directions dir) {
      this.dir = dir;
   }
   public void getMyDirection() {
     switch (dir) {
       case EAST:
          System.out.println("In East Direction");
          break;
                    
       case WEST:
          System.out.println("In West Direction");
          break;
                         
       case NORTH: 
          System.out.println("In North Direction");
          break;
                        
       default:
          System.out.println("In South Direction");
          break;
     }
   }
    
    public static void main(String[] args) {
        EnumDemo obj1 = new EnumDemo(Directions.EAST);
        obj1.getMyDirection();
        EnumDemo obj2 = new EnumDemo(Directions.SOUTH);
        obj2.getMyDirection();
    }
}
Output:
In East Direction
In South Direction
Xem các giá trị của enum.
class EnumDemo
{
    public static void main(String[] args) {
     for (Directions dir : Directions.values()) {
         System.out.println(dir);
     }
    }
}
Output:
EAST
WEST
NORTH 
SOUTH

[Java] Inner class trong Java

a. Định nghĩa một Inner class.
Một Inner class được định nghĩa trong cặp dấu "{}" của Outer class.
package simplecodecjava.blogspot.com;

//Outer class - chứa Inner class
public class OuterClassDemo {
 private int myVar = 1;

 // Định nghĩa Inner class
 class InnerClassDemo {
  public void seeOuter() {
   System.out.println("Value of myVar is :" + myVar);
  }
 } // close Định nghĩa Inner class
} // close Định nghĩa Outer class
Inner class được định nghĩa trong cặp dấu "{}" nên Inner class được coi là một thành phần của Outer class, do đó Inner class cũng có thể định nghĩa phạm vi truy cập như đối với các biến của Outer class như: abstract, final, public, protected, private, static, đồng thời Inner class cũng có thể truy cập tới các các biến này. Ở ví dụ trên biến myVar được truy cập từ trong phương thức của Inner class.
b. Khởi tạo một đối tượng của Inner class.
Có 2 cách để khởi tạo một đối tượng có kiểu Inner class.
Khởi tạo Inner class thông qua khởi tạo Outer class.
Vì Inner class là một thành phần của Outer class do đó Inner class tồn tại bên trong một đối tượng của Outer class.
package simplecodecjava.blogspot.com;

//Outer class - chứa Inner class
public class OuterClassDemo {
 private int x = 1;

 public void innerInstance() {
  InnerClassDemo inner = new InnerClassDemo();
  inner.seeOuter();
 }

 public static void main(String args[]) {
  OuterClassDemo obj = new OuterClassDemo();
  obj.innerInstance();
 }

 // Định nghĩa Inner class
 class InnerClassDemo {
  public void seeOuter() {
   System.out.println("Giá strị của x is :" + x);
  }
 } // close định nghĩa Inner class
} // close Outer class
Output:
Giá trị của x is :1
Khơi tạo trực tiếp Inner class không cần khởi tạo Outer class
Inner class cũng được khởi tạo bằng từ khóa new.
 public static void main(String args[]) {
  OuterClassDemo.InnerClassDemo inner = new OuterClassDemo().new InnerClassDemo();
  inner. seeOuter();
 }

Friday, December 18, 2015

[Java] Loại bỏ phần tử lặp trong ArrayList.

Trong bài viết này chúng ta sẽ học cách loại bỏ phần tử lặp có trong ArrayList. Các bước thực hiện như sau.
  1. Copy tất cả các phần tử của ArrayList cho LinkedHashSet.Tại sao lại là LinkedHashSet ? Bởi LinkedHashSet có thể loại bỏ các phần tử lặp và giữ cho việc chèn các phần tử theo thứ tự.
  2. Loại bỏ tất cả các phần tử của ArrayList.
  3. Copy tất cả các phần tử của LinkedHashSet cho ArrayList.
Chương trình cài đặt loại bỏ các phần tử lặp có trong ArrayList.
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
 
public class RemoveDuplicates {
 public static void main(String[]args){
  List<string> list = new ArrayList<string>();
  list.add("Hà Nội");
  list.add("Huế");
  list.add("Đà Nẵng");
  list.add("TP. Hồ Chí Minh");
  list.add("Hà Nội");
  System.out.println("Trước khi loại bỏ phần tử lặp:");
  for (String item : list) {
   System.out.println(item);
  }
  LinkedHashSet<string> linkedHashSet = new LinkedHashSet<string>();
  //copy các phần tử của list cho linkedHashset.
  linkedHashSet.addAll(list);
  //Loại bỏ tất cả các phần tử của ArrayList
  list.clear();
  //Copy tất cả các phần tử của LinkedHashSet cho ArrayList.
  list.addAll(linkedHashSet);
  System.out.println("Sau khi loại bỏ phần tử lặp:");
  for (String item : list) {
   System.out.println(item);
  }
 }
}
Output:
Trước khi loại bỏ phần tử lặp:
Hà Nội
Huế
Đà Nẵng
TP. Hồ Chí Minh
Hà Nội
Sau khi loại bỏ phần tử lặp:
Hà Nội
Huế
Đà Nẵng
TP. Hồ Chí Minh

[Java] Có thể khởi chạy Thread 2 lần không ?

Có thể khởi  chạy Thread 2 lần không ? Câu trả lời là không. Một thread khi đã khởi chạy thì nó không thể được khởi chạy lại. Nếu gọi khởi chạy thread lần thứ 2 Java sẽ ném ra một exception IllegalThreadStateException. Hãy xem ví dụ sau:
public class ThreadTwiceExample implements Runnable {
   public void run(){  
 Thread t = Thread.currentThread();
        System.out.println(t.getName()+" đang thực thi.");
      
   }  
   public static void main(String args[]){  
 Thread th1 = new Thread(new ThreadTwiceExample(), "thread1"); 
 th1.start();  
 th1.start();  
   } 
}
Khi chạy chương trình trên sẽ có thông báo lỗi như sau:
Exception in thread "main" thread1 đang thực thi.
java.lang.IllegalThreadStateException
 at java.lang.Thread.start(Unknown Source)
 at ThreadTwiceExample.main(ThreadTwiceExample.java:10)
Nhìn vào kết quả của chương trình trên phương thức run đã được gọi khi lệnh sau được thực thi:
th1.start();
Nhưng Java ném ra một lỗi khi phương thức trên được gọi đến lần thứ 2.

Wednesday, December 2, 2015

JSON Tutorial - Kiến thức căn bản về JSON.

1. JSON
JSON là viết tắt của JavaScript Object Notation. JSON được sử dụng để truyền dữ liệu giữa Server và Client, XML cũng được sử dụng để truyền dữ liệu giữa Server và Client. Tuy nhiên việc truyền dữ liệu bằng JSON Objects có một vài lợi thế so với XML. Bài viết này sẽ đưa ra cái nhìn tổng quan về JSON và cách sử dụng JSON.
Dữ liệu kiểu JSON là một cặp key - value.
var student = {
   "firstName" : "Hạnh",
   "lastName" : "Nguyễn",
   "age" :  "23"
}; 
Với các chú ý sau:
- Chuỗi JSON được được bắt đầu và kết thúc bằng cặp dấu '{}'.
- Các key và value của JSON được đặt trong dấu nháy kép   " " . Nếu value có chứa dấu nháy kép ' " ' thì cần phải đặt ký tự ' \ ' trước dấu nháy kép. Ví dụ value = "simplecodecjava.blogspot.com" thì khi định nghĩa dữ liệu trong JSON phải viết là \"simplecodecjava.blogspot.com\".
- Nếu có nhiều dữ liệu ( nhiều cặp key-value) thì ta dùng dấu ' ,' để ngăn cách các cặp dữ liệu.
- Các key của JSON thường được đặt là các chữ cái không dấu, chữ số, dấu '_' và không có khoảng trắng.
2. Đặc trưng của JSON
- Là kiểu dữ liệu nhẹ.
- Không phụ thuộc vào ngôn ngữ.
- Dễ đọc và viết.
- Viết dựa trên text, nên có thể dễ dàng hiểu nội dung của JSON.
 3. Tại sao sử dụng JSON.
 - Cấu trúc chuẩn: JSON được định nghĩa theo một cấu trúc chuẩn nó giúp cho Developer dễ dàng đọc, viết và hiểu. Vì vậy mà các Developer thường chọn JSON.
- Là kiểu dữ liệu nhẹ: Khi làm việc với AJAX cần phải load dữ liệu nhanh và đồng bộ mà không cần phải gửi request lại. Vì JSON là kiểu dữ liệu nhẹ nên việc tải và request dữ liệu nhanh hơn.
- Khả năng linh hoạt: JSON không phụ thuộc vào ngôn ngữ, điều đó có nghĩa là nó hoạt động tốt với hầu hết tất cả các ngôn ngữ lập trình hiện đại. Giả xử khi cần thay đổi ngôn ngữ lập trình bên phía server, trong trường hợp này việc thay đổi kiến trúc của JSON trở nên dễ dàng cho mọi ngôn ngữ lập trình.
4. JSON vs. XML
Hãy xem cách mà JSON và XML lưu trữ 4 bản ghi học sinh .
Dữ liệu dưới dạng JSON.
{"students":[
   {"name":"Tuấn", "age":"23", "city":"Hà Nội"},
   {"name":"Đạt", "age":"28", "city":"Đà Nẵng"},
   {"name":"Lan", "age":"32", "city":"Thừa Thiên Huế"},
   {"name":"Yến", "age":"28", "city":"TP.Hồ Chí Minh"}
]}
Dữ liệu dưới dạng XML.
<students>
  <student>
    <name>Tuấn</name> <age>23</age> <city>Hà Nội</city>
  </student>
  <student>
    <name>Đạt</name> <age>28</age> <city>Đà Nẵng</city>
  </student>
  <student>
    <name>Lan</name> <age>32</age> <city>Thừa Thiên Huế</city>
  </student>
  <student>
    <name>Yến</name> <age>28</age> <city>TP.Hồ Chí Minh</city>
  </student>
</students>
Có thể dễ dàng thấy rằng dữ liệu dưới dạng JSON thì  nhẹ hơn so với dữ liệu dưới dạng XML.
5. Kiến trúc dữ liệu kiểu và cách đọc JSON.
a. Đối tượng JSON.
var person= {
  "name" : "ZappyMans",
  "age" = "24",
  "website" = "simplecodecjava.blogspot.com"
};
Để truy cập đữ liệu cho đối tượng JSON ở trên chúng ta viết key theo sau tên đối tượng theo mẫu sau:
<đối_tượng>.<key>
ví dụ:
Tên của đối tượng person: person.name
Tuổi của đối tượng person: person.age
Website của đối tượng person: person.website
b. Mảng đối tượng JSON.
Phần trên trình bày cách lưu trữ thông tin của một đối tượng person. Giả sử muốn lưu thông tin của nhiều hơn một đối tượng, trong trường hợp này chúng ta dùng mảng.
var students = [{
   "name" : "Lan",
   "age" :  "23",
   "gender" : "Nữ"
},
{
   "name" : "Tuấn",
   "age" : "24",
   "gender" : "Nam"
},
{
   "name" : "Yến",
   "age" : "21",
   "gender" : "Nữ"
}];
Để truy cập và lấy ra dữ liệu của một phần tử trong mảng, ta chèn thêm chỉ số và phần tử của mảng.
Tên của học sinh thứ 1: students[0].name // Lan
Tuổi của học sinh thứ 2: students[1].age //24
Giới tính của học sinh thứ 3: students[2].gender //Nữ 
c. Khai báo JSON theo cấu trúc lồng nhau.
Cách khác để truy cập và lấy ra dữ liệu của một phần tử của trong một mảng JSON được khai báo lồng nhau.
var students = {
  "Lan" : {
  "name" : "Lan",
  "age" :  "23",
  "gender" : "Nữ" 
},

"Tuấn" : {
  "name" : "Tuấn",
  "age" : "24",
  "gender" : "Nam"
},

"Yến" : {
  "name" : "Yến",
  "age" : "21",
  "gender" : "Nữ"
}
}
Tuổi của Lan : student.Lan.age // 23
Giới tính của Tuấn: student.Tuấn.gender // Nam
6. JSON và JavaScript.
JSON được xem là 'tập con' của JavaScript nhưng không có nghĩa là nó không thể dùng được với các ngôn ngữ khác. Trên thực tế JSON được sử dụng rất hiệu quả với PHP, Perl, Python, Ruby, Java, Ajax và nhiều ngôn ngữ nữa.
Để chứng minh JSON có thể sử dụng với JavaScript, hãy xem ví dụ sau.
a. Đọc dữ liệu từ file JSON và chuyển đổi thành JavaScript Object.
var student = {
   "firstName" : "Hạnh",
   "lastName" : "Nguyễn",
   "age" :  "23"
}; 
Để chuyển đối tượng JSON Object phía trên thành JavaScript Object sử dụng phương thức parse của JSON.
var javaScriptObject = JSON.parse(student); 
b. Chuyển đối tượng JavaScript Object thành JSON text 
Sử dụng phương thức stringify.
 var jsonObject = JSON.stringify(myObject);

Monday, November 30, 2015

[Java] Sắp xếp ArrayList trong Java

1. Sắp xếp mảng String ArrayList
Để sắp  xếp ArrayList có kiểu dữ liệu là String, ta dùng method Collections.sort(arraylist), dữ liệu được chứa trong ArrayList sẽ được sắp xếp theo thứ tự alphabetic.
Ví dụ.
package simplecodecjava.blogspot.com;

import java.util.ArrayList;
import java.util.Collections;

public class SortingInArrayList {
 public static void main(String[] args){
  ArrayList<String> arrayList = new ArrayList<>();
  arrayList.add("Hà Nội");
  arrayList.add("Đà Nẵng");
  arrayList.add("Nha Trang");
  arrayList.add("TP.Hồ Chí Minh");
  System.out.println("Trước khi sắp xếp");
  for(String item: arrayList){
   System.out.println(item);
  }
  Collections.sort(arrayList);
  System.out.println("Sau khi sắp xếp");
  for(String item: arrayList){
   System.out.println(item);
  }
 }
}
Kết quả output:
Trước khi sắp xếp
Hà Nội
Đà Nẵng
Nha Trang
TP.Hồ Chí Minh
Sau khi sắp xếp
Hà Nội
Nha Trang
TP.Hồ Chí Minh
Đà Nẵng
*note: Trong bảng mã Unicode ký tự Đ đứng sau ký tự T 
2. Sắp xếp mảng Interger ArrayList.
Tương tự như với mảng String, phương thức Collections.sort(arraylist) cũng được dùng để sắp xếp mảng Interger.
Ví dụ
package simplecodecjava.blogspot.com;

import java.util.ArrayList;
import java.util.Collections;

public class SortingInArrayList {
 public static void main(String[] args){
  ArrayList<Integer> arrayList = new ArrayList<>();
  arrayList.add(10);
  arrayList.add(2);
  arrayList.add(221);
  arrayList.add(991);
  System.out.println("Trước khi sắp xếp");
  for(Integer item: arrayList){
   System.out.println(item);
  }
  Collections.sort(arrayList);
  System.out.println("Sau khi sắp xếp");
  for(Integer item: arrayList){
   System.out.println(item);
  }
 }
}
Output:
Trước khi sắp xếp
10
2
221
991
Sau khi sắp xếp
2
10
221
991
3. Sắp xếp mảng Object ArrayList
Phương thức Collections.sort(arraylist) cũng được dùng để sắp xếp mảng đối tượng, tuy nhiên đối tượng cần phải là lớp thực thi của Comparable interaface hoặc viết lại phương thức compare của Comparator interface.
Trước tiên hãy xem ví dụ sau khi dùng Collections.sort(arraylist) mà chưa cài đặt bằng một trong hai cách trên.
package simplecodecjava.blogspot.com;

public class Student {
 private int MSV;
 private String ten;
 private int namsinh;
 private String khoa;
 public Student(int MSV, String ten, int namsinh, String khoa){
  this.MSV = MSV;
  this.ten = ten;
  this.namsinh = namsinh;
  this.khoa = khoa;
 }
 @Override
 public String toString() {
  return MSV + " - " + ten + " - " + namsinh + " - " + khoa;
 }
}
Main chương trình:
package simplecodecjava.blogspot.com;

import java.util.ArrayList;
import java.util.Collections;

public class SortingInArrayList {
 public static void main(String[] args){
  ArrayList<Student> arrayList = new ArrayList<Student>();
  arrayList.add(new Student(1, "Cảnh", 1991, "Công nghệ thông tin"));
  arrayList.add(new Student(5, "Tuấn", 1992, "Công nghệ thông tin"));
  arrayList.add(new Student(9, "Việt", 1994, "Điện tử viễn thông"));
  arrayList.add(new Student(1, "Tú Anh", 1993, "Công nghệ thông tin"));
  arrayList.add(new Student(1, "Liên", 1991, "Điện tử viễn thông"));
  arrayList.add(new Student(1, "Hiệp", 1990, "Điện tử viễn thông"));
  arrayList.add(new Student(1, "Quỳnh", 1992, "Công nghệ thông tin"));
  System.out.println("Trước khi sắp xếp");
  for(Student item: arrayList){
   System.out.println(item);
  }
  Collections.sort(arrayList);
  System.out.println("Sau khi sắp xếp");
  for(Student item: arrayList){
   System.out.println(item);
  }
 }
}
Với chương trình main trên, sẽ có thông báo lỗi ở dòng
Collections.sort(arrayList);
Với lỗi thông báo như sau:
Bound mismatch: The generic method sort(List) of type Collections is not applicable for the arguments 
 (ArrayList). The inferred type Student is not a valid substitute for the bounded parameter >
Lỗi trên có thể được fix bằng một trong hai cách sau:
3.1 Cài đặt Class Student là lớp thực thi của Comparable interaface.
package simplecodecjava.blogspot.com;

public class Student implements Comparable<Student>{
 private int MSV;
 private String ten;
 private int namsinh;
 private String khoa;
 public Student(int MSV, String ten, int namsinh, String khoa){
  this.MSV = MSV;
  this.ten = ten;
  this.namsinh = namsinh;
  this.khoa = khoa;
 }
 @Override
 public String toString() {
  return MSV + " - " + ten + " - " + namsinh + " - " + khoa;
 }
 // sắp xếp sinh viên theo tên và theo khoa.
 @Override
 public int compareTo(Student o) {
  if(this.khoa.compareTo(o.khoa)== 0){
   return this.ten.compareTo(o.ten);
  }else{
   return this.khoa.compareTo(o.khoa);
  }
 }
}
Output: Sắp  xếp sinh viên theo khoa và theo tên theo thứ tự tăng dần.
Trước khi sắp xếp
1 - Cảnh - 1991 - Công nghệ thông tin
5 - Tuấn - 1992 - Công nghệ thông tin
9 - Việt - 1994 - Điện tử viễn thông
10 - Tú Anh - 1993 - Công nghệ thông tin
22 - Liên - 1991 - Điện tử viễn thông
17 - Hiệp - 1990 - Điện tử viễn thông
23 - Quỳnh - 1992 - Công nghệ thông tin
Sau khi sắp xếp
1 - Cảnh - 1991 - Công nghệ thông tin
23 - Quỳnh - 1992 - Công nghệ thông tin
5 - Tuấn - 1992 - Công nghệ thông tin
10 - Tú Anh - 1993 - Công nghệ thông tin
17 - Hiệp - 1990 - Điện tử viễn thông
22 - Liên - 1991 - Điện tử viễn thông
9 - Việt - 1994 - Điện tử viễn thông
3.2 Viết lại phương thức compare của Comparator interface.
Với cách này chúng ta không cần cài đặt Student là lớp thực thi từ Comparator interface như ở 3.1, thay vào đó phương thức compare của Comparator interace được viết lại như sau:
package simplecodecjava.blogspot.com;
import java.util.Comparator;
public class Student{
 private int MSV;
 private String ten;
 private int namsinh;
 private String khoa;
 public Student(int MSV, String ten, int namsinh, String khoa){
  this.MSV = MSV;
  this.ten = ten;
  this.namsinh = namsinh;
  this.khoa = khoa;
 }
 @Override
 public String toString() {
  return MSV + " - " + ten + " - " + namsinh + " - " + khoa;
 }
 public static Comparator<Student> compare = new Comparator<Student>() {

  @Override
  public int compare(Student o1, Student o2) {
   if(o1.khoa.compareTo(o2.khoa)== 0){
    return o1.ten.compareTo(o2.ten);
   }else{
    return o1.khoa.compareTo(o2.khoa);
   }
  }
 };
 }
Main chương trình:
package simplecodecjava.blogspot.com;

import java.util.ArrayList;
import java.util.Collections;

public class SortingInArrayList {
 public static void main(String[] args){
  ArrayList<Student> arrayList = new ArrayList<Student>();
  arrayList.add(new Student(1, "Cảnh", 1991, "Công nghệ thông tin"));
  arrayList.add(new Student(5, "Tuấn", 1992, "Công nghệ thông tin"));
  arrayList.add(new Student(9, "Việt", 1994, "Điện tử viễn thông"));
  arrayList.add(new Student(10, "Tú Anh", 1993, "Công nghệ thông tin"));
  arrayList.add(new Student(22, "Liên", 1991, "Điện tử viễn thông"));
  arrayList.add(new Student(17, "Hiệp", 1990, "Điện tử viễn thông"));
  arrayList.add(new Student(23, "Quỳnh", 1992, "Công nghệ thông tin"));
  System.out.println("Trước khi sắp xếp");
  for(Student item: arrayList){
   System.out.println(item);
  }
  Collections.sort(arrayList, Student.compare);
  System.out.println("Sau khi sắp xếp");
  for(Student item: arrayList){
   System.out.println(item);
  }
 }
}
Output:
Trước khi sắp xếp
1 - Cảnh - 1991 - Công nghệ thông tin
5 - Tuấn - 1992 - Công nghệ thông tin
9 - Việt - 1994 - Điện tử viễn thông
10 - Tú Anh - 1993 - Công nghệ thông tin
22 - Liên - 1991 - Điện tử viễn thông
17 - Hiệp - 1990 - Điện tử viễn thông
23 - Quỳnh - 1992 - Công nghệ thông tin
Sau khi sắp xếp
1 - Cảnh - 1991 - Công nghệ thông tin
23 - Quỳnh - 1992 - Công nghệ thông tin
5 - Tuấn - 1992 - Công nghệ thông tin
10 - Tú Anh - 1993 - Công nghệ thông tin
17 - Hiệp - 1990 - Điện tử viễn thông
22 - Liên - 1991 - Điện tử viễn thông
9 - Việt - 1994 - Điện tử viễn thông

Thursday, November 12, 2015

[Java] ArrayList trong Java

ArrayList là một Class implement (thực thi) của List Interface, được sử dụng phổ biến bởi khả năng linh động của nó. Hầu hết tất cả các developer chọn ArrayList thay vì Array truyền thống như trong C/C++.
Vấn đề với Array đó là kích thước cố định của nó, nếu Array được khai báo có kích thước n phần tử thì khi Array đã chứa đầy n phần tử thì ta không thể chèn thêm bất kỳ phần tử nào nữa. Còn ArrayList thì khác ta có thể chèm thêm tùy ý mà không cần lo lắng là ArrayList sẽ bị đầy, chính vì đặc tính này mà giúp cho ArrayList phổ biến hơn Array.
Ví dụ về ArrayList.
import java.util.ArrayList;
public class ArrayListExample {
 public static void main(String args[]) {
       /*
        *Tạo ArrayList: Thêm String
        *Dữ liệu được thêm vào có kiểu dữ liệu là String
        **/
    ArrayList<String> obj = new ArrayList<String>();
    /*This is how elements should be added to the array list*/
    obj.add("Hà Nội");
    obj.add("Đà Nẵng");
    obj.add("TP Hồ Chí Minh");
    obj.add("Hoàng Sa");
    obj.add("Trường Sa");
    System.out.println("ArrayList chứa những String sau.:"+obj);
    /*Thêm String mới vào các vị trí*/
    obj.add(0, "Nha Trang");
    obj.add(1, "Đà Lạt");
    /*Loại bỏ String khỏi ArrayList*/
    obj.remove("Đà Nẵng");
    obj.remove("TP Hồ Chí Minh");
    System.out.println("ArrayList mới nhận được:"+obj);
    /*Loại bỏ String ở vị trí 1*/
    obj.remove(1);
    System.out.println("ArrayList mới nhận được:"+obj);
    }
}
Kết quả chương trình:
ArrayList chứa những String sau.:[Hà Nội, Đà Nẵng, TP Hồ Chí Minh, Hoàng Sa, Trường Sa]
ArrayList mới nhận được:[Nha Trang, Đà Lạt, Hà Nội, Hoàng Sa, Trường Sa]
ArrayList mới nhận được:[Nha Trang, Hà Nội, Hoàng Sa, Trường Sa]
Các Method của ArrayList class.
1. add(Object o): Thêm một đối tượng vào trong ArrayList.
obj.add("Hello");
Thêm String "Hello" vào cuối ArrayList
2. add(int index, Object o): Thêm một đối tượng vào trong ArrayList ở vị trí index.
obj.add(2,"Hello");
Thêm String "Hello" vào vị trí thứ 2 của ArrayList.
3. boolean remove(Object o): Loại bỏ đối tượng o ra khỏi ArrayList.
obj.remove("Hello");
Loại bỏ String "Hello" trong ArrayList. Nếu  có String "Hello" phương thức sẽ trả về TRUE, nếu không có phương thức sẽ trả về FALSE.
4. E remove(int index): Loại bỏ đối tượng ở vị trí index.
obj.remove(1);
Loại bỏ đối  tượng ở vị trí index = 1 trong ArrayList. Kết quả trả về đối tượng ở vị trí số 1.
5. E set(int index, Object o): Được dùng để update một đối tượng, sẽ thay thế đối tượng ở vị trí index bằng đối tượng o. Phương thức trả về đối tượng ở vị trí index trước khi bị thay thế bởi đối tượng o.
obj.set(1,"Hello");
Thay thế String ở vị trí 1 bằng String "Hello", phương thức trả về String ở vị trí 1 trước khi bị thay thế bởi String "Hello".
6. int indexOf(Object o): Đưa ra vị trí của đối tượng o trong ArrayList. Nếu đối tượng không tìm thấy trong ArrayList method sẽ trả về -1.
obj.indexOf("Hello");
Trả về vị trí của String "Hello" có trong ArrayList. Nếu không có String "Hello" trong ArrayList, phương thức sẽ trả về -1.
7. Object get(int index): Trả về đối tượng của ArrayList ở vị trí index.
obj.get(1);
Trả về đối tượng ở vị trí 1.
8. int size(): Trả về số đối tượng có trong ArrayList.
obj.size();
9. boolean contains(Object o): Thực hiện kiểm tra đối tượng o có trong ArrayList hay không. Nếu có phương thức sẽ trả về TRUE, nếu không có phương thức sẽ trả về FALSE.
obj.contains("Hello");
Nếu ArayList có chứa String "Hello" phương thức sẽ trả về TRUE, nếu không chứa sẽ trả về FALSE.
10. clear(): Loại bỏ tất cả các đối tượng có trong ArrayList.
obj.clear();
Nếu bạn có câu hỏi hay góp ý xin hãy để lại ý kiến trong phần comment của bài viết.

Wednesday, November 11, 2015

[Java] HashMap trong Java và ví dụ

HashMap còn được gọi là mảng băm chứa cặp khóa - giá trị và được ký hiệu  HashMap <Key, Value> hoặc HashMap <K, V> . HashMap là implements(thực thi) của Map Interface. HaskMap tương tự như Hashtable, các phương thức của HashMap không đồng bộ (unsynchornized) và cho phép khóa và giá trị có thể nhận giá trị null. HashMap được sử dụng để lưu trữ ánh xạ giá trị vào khóa tương ứng.
HashMap không phải là một Collection có thứ tự điều đó có nghĩa là các giá trị được lấy từ HashMap ra không theo thứ tự mà chúng đã được chèn vào trong HashMap.
Ví dụ về HashMap:
Chương trình sau cài đặt hầu hết các method quan trọng của HashMap. Để biết thêm chi tiết về các phương thức bạn có thể xem thêm tại đây
package simplecodecjava;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class SimpleCodeCJava {
    public static void main(String[] args) {
     HashMap<Integer, String> hmap = new HashMap<Integer, String>();
      /*Thêm giá trị tương ứng vào các key.*/
      hmap.put(12, "Hà Nội");
      hmap.put(2, "Đà Nẵng");
      hmap.put(7, "Nha Trang");
      hmap.put(49, "Thành Phố Hồ Chí Minh");
      hmap.put(3, "Cà Mau");
      /* Hiện thị giá trị bên trong HashMap sử dụng Iterator*/
      Set set = hmap.entrySet();
      Iterator iterator = set.iterator();
      while(iterator.hasNext()) {
         Map.Entry mentry = (Map.Entry)iterator.next();
         System.out.print("key is: "+ mentry.getKey() + " & Value is: ");
         System.out.println(mentry.getValue());
      }

      /* Lấy ra giá trị dựa vào key*/
      String var= hmap.get(2);
      System.out.println("Value at index 2 is: "+var);

      /* Xóa dữ liệu dựa vào key*/
      hmap.remove(3);
      System.out.println("Map key and values after removal:");
      Set set2 = hmap.entrySet();
      Iterator iterator2 = set2.iterator();
      while(iterator2.hasNext()) {
          Map.Entry mentry2 = (Map.Entry)iterator2.next();
          System.out.print("Key is: "+mentry2.getKey() + " & Value is: ");
          System.out.println(mentry2.getValue());
       }
   }
}
Kết quả chạy chương trình:
key is: 49 & Value is: Thành Phố Hồ Chí Minh
key is: 2 & Value is: Đà Nẵng
key is: 3 & Value is: Cà Mau
key is: 7 & Value is: Nha Trang
key is: 12 & Value is: Hà Nội
Value at index 2 is: Đà Nẵng
Map key and values after removal:
Key is: 49 & Value is: Thành Phố Hồ Chí Minh
Key is: 2 & Value is: Đà Nẵng
Key is: 7 & Value is: Nha Trang
Key is: 12 & Value is: Hà Nội
Danh sách phương thức của HashMap.
  1. void clear(): Loại bỏ tất cả các cặp khóa và giá trị ra khỏi HashMap.
  2. Object clone(): Trả về một bản copy tất cả các cặp khóa và giá trị, thường được sử dụng để sao chép sang một HashMap khác.
  3. boolean containsKey(Object key): trả về TRUE nếu trong HashMap có chứa key, trả về FALSE nếu trong HashMap không chứa key.
  4. boolean containsValue(Object value): trả về TRUE nếu trong HashMap có chứa value, trả về FALSE nếu trong HashMap không chứa value.
  5. Value get(Object key): Trả về giá trị được ánh xạ bởi key tương ứng.
  6. boolean isEmpty(): Thực hiện kiểm tra HashMap có rỗng hay không.
  7. Set keySet(): Trả về Set - danh sách tất cả các key được lấy từ HashMap.
  8. Value put(Key k, Value v): Chèn thêm value vào trong HashMap với key tương ứng.
  9. int size(): Trả về số lượng phần tử có trong HashMap.
  10. Collection values(): Trả về danh sách tất cả các giá trị có trong HashMap.
  11. Value remove(Object key): Trả về cặp khóa giá trị tương ứng với key truyền vào.
  12. void putAll(Map m): Copy tất cả các giá trị của HashMap vào Map truyền vào.

Saturday, October 10, 2015

[Java] Danh sách liên kết

Nội dung phần này tập trung cài đặt hai loại danh sách liên kết cơ bản:
•  Danh sách liên kết đơn
•  Danh sách liên kết kép
1. Định nghĩa một nút
Để đơn giản, ta chỉ định nghĩa một nút có giá trị kiểu int:
//Chương trình 1a
public class Node{
 private int value;
 /* Các phương thức khởi dựng */
 public Node(){
  value = 0;
 }
 public Node(int value){
  this.value = value;
 }
 /* Phương thức truy nhập thuộc tính value */
 public int getValue(){
  return value;
 }
 public void setValue(int value){
  this.value = value;
 }
}
2. Danh sách liên kết đơn
a. Định nghĩa một nút của danh sách liên kết đơn
Một nút của danh sách liên kết đơn bao gồm:
•  Giá trị của nút, có dạng là một đối tượng kiểu Node đã được định nghĩa trong chương trình 1a
•  Nút tiếp theo của nút đó.
Một nút của danh sách liên kết đơn được cài đặt trong chương trình 1b.
//Chương trình 1b
public class SimpleNode{
 private Node value;   // Giá trịcủa node là một đối tượng kiểu Node
 private SimpleNode next; // Node tiếp theo của danh sách liên kết 
 /* Các phương thức khởi dựng */
 public SimpleNode(){
  value = new Node();
  next = null;
 }
 public SimpleNode(Node value){
  this.value = value;
  next = null;
 }
 /* Phương thức truy nhập thuộc tính value */
 public Node getValue(){
  return value;
 }
 public void setValue(Node value){
  this.value = value;
 }
 /* Phương thức truy nhập thuộc tính next */
 public SimpleNode getNext(){
  return next;
 }
 public void setNext(SimpleNode next){
  this.next = next;
 }
}
b. Định nghĩa đỉnh tiêu đề của danh sách liên kết đơn
Đỉnh tiêu đề của danh sách liên kết đơn là một đối tượng khác với một nút thông thường của danh sách. Đối tượng này lưu các thông tin:
•  Chỉ đến nút thực sự đầu tiên của danh sách
•  Chỉ đến nút cuối cùng của danh sách
•  Lưu giữ số lượng nút thực sự trong danh sách.
Chương trình 1c cài đặt lớp đỉnh tiêu đề của danh sách.
//Chương trình 1c
public class HeaderSimpleNode{
 private int nodeNumber;
 private SimpleNode header;
 private SimpleNode tailer;
 /* Phương thức khởi dựng */
 public HeaderSimpleNode(){
  nodeNumber = 0;
  header = null;
  tailer = null;
 }
 /* Phương thức truy nhập thuộc tính nodeNumber */
 public int getNodeNumber(){
  return nodeNumber;
 }
 public void setNodeNumber(int nodeNumber){
  this.nodeNumber = nodeNumber;
 }
 /* Phương thức truy nhập thuộc tính header */
 public SimpleNode getHeader(){
  return header;
 }
 public void setHeader(SimpleNode header){
  this.header = header;
 }
 /* Phương thức truy nhập thuộc tính tailer */
 public SimpleNode getTailer(){
  return tailer;
 }
 public void setTailer(SimpleNode tailer){
  this.tailer = tailer;
 }
}
c. Cài đặt danh sách liên kết đơn
Danh sách liên kết đơn có thuộc tính cục bộ là một đối tượng kiểu HeaderSimpleNode. Và có các thao tác chính:
 • Thêm một phần tử vào một vịtrí bất kì: nếu vịtrí nhỏ hơn 0, thêm vào đầu danh sách. Nếu vị trí lớn hơn độ dài danh sách, thêm vào cuối. Trường hợp còn lại, chèn vào danh sách một cách bình thường. • Loại bỏ một phần tử ở vị trí bất kì: Chỉ loại bỏ khi vị trí chỉ ra nằm trong phạm vi độ dài danh sách. Phương thức này trả về nút bị loại bỏ, có kiểu SimpleNode.
 • Duyệt toàn bộ danh sách: Trả về giá trị của tất cả các phần tử có trong danh sách. Giá trịtrả về là một mảng các phần tử giá trị có kiểu Node.
Chương trình 1d cài đặt lớp danh sách liên kết đơn.
//Chương trình 1d
public class SimpleList{
 private HeaderSimpleNode myList;
 /* Các phương thức khởi dựng */
 public SimpleList(){
  myList = new HeaderSimpleNode();
 }
 /* Phương thức chèn thêm một node vào vịtrí @position */
 public void insert(Node value, int position){
  // Tạo một node mới 
  SimpleNode newNode = new SimpleNode(value);
  if (position <= 0){ // Chèn vào đầu 
   newNode.setNext(myList.getHeader());
   myList.setHeader(newNode);
   if (myList.getNodeNumber() == 0) // Danh sách ban đầu rỗng 
    myList.setTailer(newNode);
  }
  else if (position >= myList.getNodeNumber()){ // Chèn vào cuối 
   if (myList.getNodeNumber() == 0){ // Danh sách ban đầu rỗng 
    myList.setHeader(newNode);
    myList.setTailer(newNode);
   }
   else{ // Danh sách không rỗng 
    myList.getTailer().setNext(newNode);
    myList.setTailer(newNode);
   }
  }
  else{ // Chèn vào giữa 
   int index = 0;
   SimpleNode prev = null;
   SimpleNode current = myList.getHeader();
   while (index < position){
    index++;
    prev = current;
    current = current.getNext();
   }
   newNode.setNext(current);
   prev.setNext(newNode);
  }
  // Cập nhật sốlượng node của danh sách 
  myList.setNodeNumber(myList.getNodeNumber() + 1);
 }
 /* Phương thức loại bỏmột node ởvịtrí @position */
 public SimpleNode remove(int position){
  if ((myList.getNodeNumber() == 0) ||
   (position < 0) || (position >= myList.getNodeNumber()))
   return null;
  SimpleNode result = null;
  if (position == 0){ // Loại phần tử đầu 
   result = myList.getHeader();
   myList.setHeader(myList.getHeader().getNext()); if (myList.getNodeNumber() == 1) // Danh sách chỉcó 1 phần tử
    myList.setTailer(null);
  }
  else if (position == myList.getNodeNumber() - 1){ // Loại phần tửcuối 
   result = myList.getTailer();
   SimpleNode current = myList.getHeader();
   while (!current.getNext().equals(myList.getTailer()))
    current = current.getNext();
   current.setNext(null);
   myList.setTailer(current);
  }
  else{ // Loại phần tửnằm giữa danh sách 
   int index = 0;
   SimpleNode prev = null;
   SimpleNode current = myList.getHeader();
   while (index < position){
    index++;
    prev = current;
    current = current.getNext();
   }
   prev.setNext(current.getNext());
   result = current;
  }
  // Cập nhật sốlượng node của danh sách 
  myList.setNodeNumber(myList.getNodeNumber() - 1);
  result.setNext(null);
  return result;
 }
 /* Phương thức duyệt toàn bộdanh sách */
 public Node[] travese(){
  // Danh sách rỗng 
  if (myList.getNodeNumber() == 0)
   return null;
  // Danh sách không rỗng 
  Node[] result = new Node[myList.getNodeNumber()];
  SimpleNode current = myList.getHeader();
  int index = 0;
  while (current != null){
   result[index] = current.getValue();
   index++;
   current = current.getNext();
  }
  return result;
 }
}
2. Danh sách liên kết kép
a. Định nghĩa một nút của danh sách liên kết kép
Một nút của danh sách liên kết kép bao gồm:
•  Giá trịcủa nút, có dạng là một đối tượng kiểu Node đã được định nghĩa trong chương trình 1a
•  Nút tiếp theo của nút đó.
•  Nút trước của nút đó.
Một nút của danh sách liên kết kép được cài đặt trong chương trình 2a.
//Chương trình 2a
public class DoubleNode{
 private Node value;
 private DoubleNode prev;
 private DoubleNode next;
 /* Các phương thức khởi dựng */
 public DoubleNode(){
  value = new Node();
  prev = null;
  next = null;
 }
 public DoubleNode(Node value){
  this.value = value;
  prev = null;
  next = null;
 }
 /* Phương thức truy nhập thuộc tính value */
 public Node getValue(){
  return value;
 }
 public void setValue(Node value){
  this.value = value;
 }
 /* Phương thức truy nhập thuộc tính next */
 public DoubleNode getNext(){
  return next;
 }
 public void setNext(DoubleNode next){
  this.next = next;
 }
 /* Phương thức truy nhập thuộc tính prev */
 public DoubleNode getPrev(){
  return prev;
 }
 public void setPrev(DoubleNode prev){
  this.prev = prev;
 }
}
b. Định nghĩa đỉnh tiêu đề của danh sách liên kết kép
Đỉnh tiêu đề của danh sách liên kết đơn là một đối tượng khác với một nút thông thường của danh sách. Đối tượng này lưu các thông tin: • Chỉ đến nút thực sự đầu tiên của danh sách • Chỉ đến nút cuối cùng của danh sách • Lưu giữ số lượng nút thực sự trong danh sách. Chương trình 2b cài đặt lớp đỉnh tiêu đề của danh sách.
//Chương trình 2b
public class HeaderDoubleNode{
 private int nodeNumber;
 private DoubleNode header;
 private DoubleNode tailer;
 /* Phương thức khởi dựng */
 public HeaderDoubleNode(){
  nodeNumber = 0;
  header = null;
  tailer = null;
 }
 /* Phương thức truy nhập thuộc tính nodeNumber */
 public int getNodeNumber(){
  return nodeNumber;
 }
 public void setNodeNumber(int nodeNumber){
  this.nodeNumber = nodeNumber;
 }
 /* Phương thức truy nhập thuộc tính header */
 public DoubleNode getHeader(){
  return header;
 }
 public void setHeader(DoubleNode header){
  this.header = header;
 }
 /* Phương thức truy nhập thuộc tính tailer */
 public DoubleNode getTailer(){
  return tailer;
 }
 public void setTailer(DoubleNode tailer){
  this.tailer = tailer;
 }
}
c. Cài đặt danh sách liên kết kép
Danh sách liên kết kép có thuộc tính cục bộ là mộ đối tượng kiểu HeaderDoubleNode. Và có các thao tác chính:
•  Thêm một phần tử vào một vị trí bất kì: nếu vị trí nhỏ hơn 0, thêm vào đầu danh sách. Nếu vị trí lớn hơn độ dài danh sách, thêm vào cuối. Trường hợp còn lại, chèn vào danh sách một cách bình thường.
•  Loại bỏ một phần tử ở vị trí bất kì: Chỉ loại bỏ khi vị trí chỉ ra nằm trong phạm vi độ dài danh sách. Phương thức này trả về nút bị loại bỏ, có kiểu DoubleNode.
•  Duyệt toàn bộ danh sách: Trả về giá trị của tất cả các phần tử có trong danh sách. Giá trịtrả về là một mảng các phần tử giá trị có kiểu Node.
Chương trình 2c cài đặt lớp danh sách liên kết kép.
//Chương trình 2c
public class DoubleList{
 private HeaderDoubleNode myList;
 /* Các phương thức khởi dựng */
 public DoubleList(){
  myList = new HeaderDoubleNode();
 }
 /* Phương thức chèn thêm một node vào vịtrí @position */
 public void insert(Node value, int position){
  // Tạo một node mới 
  DoubleNode newNode = new DoubleNode(value);
  if (position <= 0){ // Chèn vào đầu 
   newNode.setNext(myList.getHeader());
   myList.getHeader().setPrev(newNode);
   myList.setHeader(newNode);
   if (myList.getNodeNumber() == 0) // Danh sách ban đầu rỗng 
    myList.setTailer(newNode);
  }
  else if (position >= myList.getNodeNumber()){ // Chèn vào cuối 
   if (myList.getNodeNumber() == 0){ // Danh sách ban đầu rỗng 
    myList.setHeader(newNode);
    myList.setTailer(newNode);
   }
   else{ // Danh sách không rỗng 
    newNode.setPrev(myList.getTailer());
    myList.getTailer().setNext(newNode);
    myList.setTailer(newNode);
   }
  }
  else{ // Chèn vào giữa 
   int index = 0;
   DoubleNode current = myList.getHeader();
   while (index < position){
    index++;
    current = current.getNext();
   }
   newNode.setNext(current);
   newNode.setPrev(current.getPrev());
   current.getPrev().setNext(newNode);
   current.setPrev(newNode);
  }
  // Cập nhật sốlượng node của danh sách 
  myList.setNodeNumber(myList.getNodeNumber() + 1);
 }
 /* Phương thức loại bỏmột node ởvịtrí @position */
 public DoubleNode remove(int position){
  if ((myList.getNodeNumber() == 0) ||
   (position < 0) || (position >= myList.getNodeNumber()))
   return null;
  DoubleNode result = null;
  if (position == 0){ // Loại phần tử đầu 
   result = myList.getHeader();
   myList.setHeader(myList.getHeader().getNext());
   if (myList.getHeader() != null)
    myList.getHeader().setPrev(null);
   if (myList.getNodeNumber() == 1) // Danh sách chỉcó 1 phần tử
    myList.setTailer(null);
  }
  else if (position == myList.getNodeNumber() - 1){ // Loại phần tửcuối 
   result = myList.getTailer();
   myList.setTailer(myList.getTailer().getPrev());
   myList.getTailer().setNext(null);
  }
  else{ // Loại phần tửnằm giữa danh sách 
   int index = 0;
   DoubleNode current = myList.getHeader();
   while (index < position){
    index++;
    current = current.getNext();
   }
   current.getPrev().setNext(current.getNext());
   current.getNext().setPrev(current.getPrev());
   result = current;
  }
  // Cập nhật sốlượng node của danh sách 
  myList.setNodeNumber(myList.getNodeNumber() - 1);
  result.setPrev(null);
  result.setNext(null);
  return result;
 }
 /* Phương thức duyệt toàn bộdanh sách */
 public Node[] travese(){
  // Danh sách rỗng 
  if (myList.getNodeNumber() == 0)
   return null;
  // Danh sách không rỗng 
  Node[] result = new Node[myList.getNodeNumber()];
  DoubleNode current = myList.getHeader();
  int index = 0;
  while (current != null){
   result[index] = current.getValue();
   index++;
   current = current.getNext();
  }
  return result;
 }
}

[Java] Ngăn xếp và Hàng đợi


1. Định nghĩa một nút
Để đơn giản, ta chỉ định nghĩa một nút có giá trị kiểu int:
//Chương trình 1a
public class Node{
 private int value;
 /* Các phương thức khởi dựng */
 public Node(){
  value = 0;
 }
 public Node(int value){
  this.value = value;
 }
 /* Phương thức truy nhập thuộc tính value */
 public int getValue(){
  return value;
 }
 public void setValue(int value){
  this.value = value;
 }
}
2. Ngăn xếp
Ngăn xếp (stack) có các thuộc tính cục bộ:
•  Mảng lưu các nút của ngăn xếp
Các thao tác đối với ngăn xếp:
•  Thêm vào một nút
•  Lấy ra một nút
Cài đặt ngăn xếp
•  Ta coi đỉnh ngăn xếp là cuối mảng lưu giữ các nút. Do đó, các thao tác thêm vào và lấy ra sẽ thêm vào cuối mảng hoặc lấy nút ở cuối mảng ra.
•  Mảng các giá trị được khai báo động để tiết kiệm bộ nhớ.
//Chương trình 1b
public class MyStack{
 private Node[] values;
 /* Các phương thức khởi dựng */
 public MyStack(){}
 public MyStack(Node[] values){
  this.values = values;
 }
 /* Phương thức lấy ra một node từstack */
 public Node pop(){
  Node result = null;
  if ((values != null) && (values.length > 0)){
   result = values[values.length - 1];
   // Loại bỏnode cuối cùng 
   Node[] tmpNode = new Node[values.length - 1];
   for (int i = 0; i < values.length – 1; i++)
    tmpNode[i] = values[i];
   this.values = tmpNode;
  }
  return result;
 }
 /* Phương thức thêm một node vào stack */
 public void push(Node node){
  if (values == null){ // Ngăn xếp đang rỗng 
   values = new Node[1];
   values[0] = node;
  }
  else{ // Ngăn xếp đã có dữliệu 
   Node[] tmpNode = new Node[values.length + 1];
   for (int i = 0; i < values.length; i++)
    tmpNode[i] = values[i];
   tmpNode[values.length] = node;
   this.values = tmpNode;
  }
 }
}
3. Hàng đợi
Hàng đợi (queue) có các thuộc tính cục bộ:
•  Mảng các giá trị trong hàng đợi
Các thao tác với hàng đợi:
•  Thêm vào một nút vào cuối hàng đợi
•  Lấy ra một nút từ đầu hàng đợi
Chương trình 2 cài đặt lớp hàng đợi
//Chương trình 2
public class MyQueu{
 private Node[] values;
 /* Các phương thức khởi dựng */
 public MyQueu(){}
 public MyQueu(Node[] values){
  this.values = values;
 }
 /* Phương thức lấy ra một node từ đầu queu */
 public Node remove(){
  Node result = null;
  if ((values != null) && (values.length > 0)){
   result = values[0];
   // Loại bỏnode đầu hàng đợi 
   Node[] tmpNode = new Node[values.length - 1];
   for (int i = 0; i<values.length – 1; i++)
    tmpNode[i] = values[i + 1];
   this.values = tmpNode;
  }
  return result;
 }
 /* Phương thức thêm một node vào cuối queu */
 public void insert(Node node){
  if (values == null){ // Hàng đợi đang rỗng 
   values = new Node[1];
   values[0] = node;
  }
  else{ // Hàng đợi đã có dữliệu 
   Node[] tmpNode = new Node[values.length + 1];
   for (int i = 0; i<values.length; i++)
    tmpNode[i] = values[i];
   tmpNode[values.length] = node;
   this.values = tmpNode;
  }
 }
}

[Java] Đa hình trên Java

1. Nạp chồng.
Java cho phép trong cùng một lớp, có thể khai báo nhiều phương thức có cùng tên. Nạp chồng là hiện tượng các phương thức có cùng tên. Có hai kiểu nạp chồng trong Java:
•  Các phương thức của cùng một lớp có cùng tên. Khi hai phương thức của một lớp có cùng tên thì bắt buộc chúng phải có:
-  Hoặc danh sách các tham số khác nhau
-  Hoặc kiểu trả về khác nhau
-  Hoặc kết hợp hai điều kiện trên.
Nếu không, java sẽ không phân biệt được chúng. Ví dụ nếu trong cùng một lớp:
// Chấp nhận được 
 public int add(int x, int y){…} 
 public float add(float x, int y){…} 
 // Không chấp nhận được 
 public int add(int x, int y){…} 
 public int add(int x, int y){…}
•  Phương thức của lớp con có cùng tên với phương thức của lớp cha. Trong trường hợp này, các phương thức nạp chồng có thể có cùng danh sách tham số và có cùng kiểu trả về.
2. Đa hình.
Đa hình là việc triệu gọi đến các phương thức nạp chồng của đối tượng. Khi một phương thức nạp chồng được gọi, chương trình sẽ dựa vào kiểu các tham số và kiểu trả về để gọi phương thức của đối tượng cho phù hợp.
Chương trình 1 minh hoạ việc khai báo nhiều hàm add() để cộng hai số hoặc cộng hai xâu kí tự.
//Chương trình 1
public class Operator
{
 // Cộng hai sốnguyên 
 public int add(int x, int y)
 {
  return (x + y);
 }
 // Cộng hai sốthực 
 public float add(float x, float y)
 {
  return (x + y);
 }
 // Cộng hai chuỗi kí tự
 public String add(String a, String b)
 {
  return (a + b);
 }
 // Hàm main 
 public static void main(String args[])
 {
  Operator myOperator = new Operator();
  System.out.println("The(5 + 19) is " + myOperator.add(5, 19));
  System.out.println("The(\"ab\" + \"cd\") is \""
   + myOperator.add("ab", "cd") + "\"");
 }
}
Chương trình 1 sẽ hiển thị ra hai dòng thông báo:
The (5+19) is 24 
The (‘ab’ + ‘cd’) is ‘abcd’
Trong lớp Operator có hai phương thức cùng tên và cùng có hai tham số đầu vào là add(). Khi chương trình thực thi lệnh myOperator.add(5, 19), chương trình sẽ tự đối chiếu các kiểu tham số, thấy 5 và 19 có dạng gần với kiểu int nhất, nên phương thức add(int, int) sẽ được gọi và trả về giá trị là 24.
Khi chương trình thực thi lệnh myOperator.add(“ab”, “cd”), chương trình sẽ tự đối chiếu các kiểu tham số, thấy ‘ab’ và ‘cd’ có dạng gần với kiểu String nhất, nên phương thức add(String, String) sẽ được gọi và trả về giá trị là ‘abcd’.
Lưu ý:
•  Khi gọi hàm với các kiểu dữ liệu khác với các hàm đã được khai báo, sẽ có sự chuyển đổi kiểu ngầm định diễn ra. Khi không thể thực hiện chuyển đổi kiểu ngầm định, java sẽ phát sinh một thông báo lỗi.
Chẳng hạn, trong chương trình 1, nếu ta thực thi lệnh myOperator.add(4.0f, 5) có dạng add(float, int), chương trình sẽ chuyển ngầm định số nguyên 5 thành float (chuyển từ kiểu int sang float thuộc diện nới rộng kiểu, là kiểu chuyển ngầm định trong java) đểcó thể sử dụng dạng được khai báo add(float, float) và kết quả sẽ là 9.0f. Nếu ta thực thi lệnh myOperator.add(‘ab’, 5) có dạng add(String, int), vì int không thể chuyển ngầm định thành String nên lệnh này sẽ phát sinh lỗi. Để tránh lỗi này, phải chuyển đổi kiểu tường minh cho số 5 thành kiểu String bằng một trong các cách sau:
myOperator.add(“ab”, (new Int(5)).toString()); 
myOperator.add(“ab”, 5 + ””);

3. Case Study về kế thừa và đa hình. 
Trong phần này, chúng ta sẽ viết một chương trình quản lí nhân viên của một công ty. Bao gồm các lớp chính:
•  Lớp Human là một lớp trừu tượng, chỉ có một phương thức duy nhất là show().
•  Lớp Person là lớp kế thừa từ lớp Human, có hai thuộc tính là tên (name) và tuổi (age). Để đóng gói dữ liệu các thuộc tính này có dạng private và các phương thức truy nhập chúng (get và set). Ngoài ra lớp này còn cài đặt phương thức show() kế thừa từ lớp trừu tượng Human.
•  Lớp Employee là lớp kế thừa từ lớp Person, có thêm thuộc tính là lương (salary). Thuộc tính này cũng có dạng private để đóng gói dữ liệu và cần các phương thức truy nhập get/set. Lớp này cài đặt lại phương thức show(). Hơn nữa, lớp Employee còn có thêm hai phương thức addSalary() và addSalary(float) để tính tăng lương cho nhân viên: một phương thức tăng lương theo tỉ lệ mặc định là 10% (không cần tham số), và một phương thức tăng theo giá trị cụ thể đưa vào (cần tham số).
Các phần tiếp theo sẽ trình bày phần cài đặt chi tiết cho các lớp này.
1 Lớp Human
Lớp Human là một lớp trừu tượng, chỉ có một phương thức duy nhất là show(). Đây là nội dung tập tin Human.java.
//Chương trình 2a
abstract class Human
{
 abstract void show();
}
2 Lớp Person
Lớp Person là lớp kế thừa từ lớp Human:
•  Có hai thuộc tính là tên (name) và tuổi (age) có dạng private
•  Các phương thức truy nhập các thuộc tính name (getName() và setName(String)) và age (getAge() và setAge(int)).
•  Cài đặt chồng phương thức show() kế thừa từ lớp trừu tượng Human.
Đây là nội dung tập tin Person.java. 
//Chương trình 2b
class Person extends Human
{
 private String name;
 private int age;
 // Phương thức khởi dựng không có tham số
 public Person()
 {
  super();
  name = “”;
  age = 0;
 }
 // Phương thức khởi dựng có tham số
 public Person(String name, int age)
 {
  this.name = name;
  this.age = age;
 }
 /* Phương thức truy nhập thuộc tính name */
 public String getName()
 {
  return name;
 }
 public void setName(String name)
 {
  this.name = name;
 }
 /* Phương thức truy nhập thuộc tính age */
 public int getAge()
 {
  return age;
 }
 public void setAge(int age)
 {
  this.age = age;
 }
 // Khai báo nạp chồng 
 public void show()
 {
  System.out.println(name + “ is ” + age + “ years old!”);
 }
}

3 Lớp Employee
Lớp Employee là lớp kế thừa từ lớp Person: • Có thêm thuộc tính là lương (salary) cũng có dạng private để đóng gói dữ liệu và cần các phương thức truy nhập get/set. • Lớp này cài đặt lại phương thức show(). • Có thêm hai phương thức addSalary() và addSalary(float) để tính tăng lương cho nhân viên: phương thức addSalary() tăng lương theo tỉ lệ mặc định là 10% (không cần tham số), phương thức addSalary(float) tăng theo giá trị cụ thể đưa vào (cần tham số). Sau đây là nội dung tập tin Employee.java.
//Chương trình 2c
class Employee extends Person
{
 private float salary;
 // Phương thức khởi dựng không có tham số
 public Employee()
 {
  super();
  salary = 0f;
 }
 // Phương thức khởi dựng có tham số
 public Employee(String name, int age, float salary)
 {
  super(name, age);
  this.salary = salary;
 }
 /* Phương thức truy nhập thuộc tính salarry */
 public float getSalary()
 {
  return salary;
 }
 public void setSalary(float salary)
 {
  this.salary = salary;
 }
 // Khai báo nạp chồng 
 public void show()
 {
  System.out.println(getName() + “ is ” + getAge()
   + “ years old having a salary of $”
   + salary + “ / month!”);
 }
 /* Phương thức tăng lương */
 public void addSalary()
 {
  salary = salary*1.1f;
 }
 public void addSalary(float addition)
 {
  salary += addition;
 }
}
Lưu ý: Trong phương thức nạp chồng show() của lớp Employee, ta phải dùng các phương thức public được kế thừa từ lớp Person là getName() và getAge() để truy nhập đến thuộc tính name và age mà không thể truy xuất trực tiếp. Lí do là các thuộc tính name và age có dạng private trong lớp Person nên không thể truy xuất trực tiếp trong các lớp dẫn xuất. Do đó, ta phải truy xuất chúng thông qua các phương thức truy nhập public của lớp Person.
4 Chương trình demo
Chương trình 2d chứa hàm main đểchạy minh hoạ việc sử dụng các lớp Person và Employee.
//Chương trình 2d
public class Casestudy2
{
 // Hàm main 
 public static void main(String args[])
 {
  // Sửdụng lớp Person 
  Person myPerson = new Person(“Vinh”, 25);
  myPerson.show();
  // Sửdụng lớp Employee 
  Employee myEmployee = new Employee(“Vinh”, 25, 300f);
  myEmployee.show();
  // Tăng lương theo mặc định 
  myEmployee.addSalary();
  myEmployee.show();
  // Tăng lương lên $50 
  myEmployee.addSalary(50f);
  myEmployee.show();
 }
}
Chương trình 2d sẽ hiển thị nội dung như sau:
Vinh is 25 years old! 
Vinh is 25 years old having a salary of $300/month! 
Vinh is 25 years old having a salary of $330/month! 
Vinh is 25 years old having a salary of $380/month!
Dòng thứ nhất in ra dòng thông báo theo phương thức show() của lớp Person. Dòng thứ hai cũng
hiển thị thông báo theo phương thức show() của lớp Employee đã được khai báo nạp chồng. Dòng
thứ ba hiển thị thông báo sau khi đã tăng lương theo mặc định (10%) từ 300$ lên 330$. Dòng thứ
tư hiển thị thông báo sau khi tăng lương thêm một lần nữa với lượng tăng là 50$ từ 330$ lên 380$.

Thursday, September 24, 2015

[Java] Cấu trúc lệnh trên Java

Java cung cấp hai loại cấu trúc điều khiển:
Điều khiển rẽ nhánh
•  Mệnh đề if-else
•  Mệnh đề swich-case
Vòng lặp (Loops)
•  Vòng lặp while
•  Vòng lặp do-while
•  Vòng lặp for
1 Câu lệnh if-else
Câu lệnh if-else kiểm tra giá trị dạng boolean của điều kiện. Nếu giá trị điều kiện là True thì chỉ có khối lệnh sau if sẽ được thực hiện, nếu là False thì chỉ có khối lệnh sau else được thực hiện. Cú pháp:
if (conditon) 
{ 
action1 statements; 
} 
else 
{ 
action2 statements; 
}
Condition: Biểu thức boolean như toán tử so sánh.
action 1: Khối lệnh được thực thi khi giá trị điều kiện là True
action 2:Khối lệnh được thực thi nếu điều kiện trả về giá trị False
Đoạn chương trình sau kiểm tra xem các số có chia hết cho 5 hay không.
package vidu.chuong3;
class CheckNumber
{
 public static void main(String args[])
 {
  int num = 10;
  if (num % 5 == 0)
   System.out.println(num + “ is divisable for 5!”);
  else
   System.out.println(num + ” is indivisable for 5!”);
 }
Ở đoạn chương trình trên num được gán giá trị nguyên là 10. Trong câu lệnh if-else điều kiện num%5 trả về giá trị 0 và điều kiện thực hiện là True. Thông báo “10 is divisable for 5!” được in ra. Lưu ý rằng vì chỉ có một câu lệnh được viết trong đoạn “if” và “else”, bởi vậy không cần thiết phải được đưa vào dấu ngoặc móc “{” và “}”.
2 Câu lệnh switch-case
Khối lệnh switch-case có thể được sử dụng thay thế câu lệnh if-else trong trường hợp một biểu thức cho ra nhiều kết quả. Cú pháp:
swich (expression) 
{ 
case ‘value1’:  action 1 statement; 
break; 
case ‘value2’:  action 2 statement; 
break; 
………………… 
case ‘valueN’: actionN statement; 
break; 
default: default_action statement; 
}
expression- Biến chứa một giá trị xác định
value1,value 2,….valueN: Các giá trị hằng số phù hợp với giá trịtrên biến expression.
action1,action2…actionN: Khối lệnh được thực thi khi trường hợp tương ứng có giá trị True
break:Từ khoá được sử dụng để bỏ qua tất cảcác câu lệnh sau đó và giành quyền điều khiển cho cấu trúc bên ngoài switch
default: Từ khóa tuỳ chọn được sử dụng để chỉ rõ các câu lệnh nào được thực hiện chỉ khi tất cả các trường hợp nhận giá trị False
default - action:Khối lệnh được thực hiện chỉ khi tất cả các trường hợp nhận giá trị False
Đoạn chương trình sau xác định giá trị trong một biến nguyên và hiển thị ngày trong tuần được thể hiện dưới dạng chuỗi. Để kiểm tra các giá trị nằm trong khoảng từ 0 đến 6, chương trình sẽ thông báo lỗi nếu nằm ngoài phạm vi trên.
package vidu.chuong3;
class SwitchDemo
{
 public static void main(String agrs[])
 {
  int day = 2;
  switch (day)
  {
  case 0: System.out.println(“Sunday”);
   break;
  case 1: System.out.println(“Monday”);
   break;
  case 2: System.out.println(“Tuesday”);
   break;
  case 3: System.out.println(“Wednesday”);
   break;
  case 4: System.out.println(“Thursday”);
   break;
  case 5:  System.out.println(“Friday”);
   break;
  case 6: System.out.println(“Satuday”);
   break;
  default:
   System.out.println(“Invalid day of week”);
  }
 }
}
Nếu giá trị của bíến day là 2, chương trình sẽ hiển thị Tuesday, và cứ tiếp như vậy .
3 Vòng lặp While
Vòng lặp while thực thi khối lệnh khi điều kiện thực thi vẫn là True và dừng lại khi điều kiện thực
thi nhận giá trị False. Cú pháp:
while(condition) 
{ 
action statements; 
}
condition:có giá trị bool; vòng lặp sẽ tiếp tục cho nếu điều kiện vẫn có giá trị True.
action statement:Khối lệnh được thực hiện nếu condition nhận giá trị True
Đoạn chương trình sau tính tổng của 5 số tự nhiên đầu tiên dùng cấu trúc while.
package vidu.chuong3;
class WhileDemo
{
 public static void main(String args[])
 {
  int a = 5, sum = 1;
  while (a >= 1)
  {
   sum += a;
   a--;
  }
  System.out.println(“The sum is “ + sum);
 }
}
Ở ví dụ trên, vòng lặp được thực thi cho đến khi điều kiện a>=1 là True. Biến a được khai báo bên ngoài vòng lặp và được gán giá trị là 5. Cuối mỗi vòng lặp, giá tri của a giảm đi 1. Sau năm vòng giá trị của a bằng 0. Điều kiện trả về giá trị False và vòng lặp kết thúc. Kết quả sẽ được hiển thị “ The sum is 15”
4 Vòng lặp do-while
Vòng lặp do-while thực thi khối lệnh khi mà điều kiện là True, tương tự như vòng lặp while,
ngoại trừ do-while thực hiện lệnh ít nhất một lần ngay cả khi điều kiện là False. Cú pháp:
do{
action statements;
}while(condition); 
condition:Biểu thức bool; vòng lặp sẽ tiếp tục khi mà điều kiện vẫn có giá trị True.
action statement:Khối lệnh luôn được thực hiện ở lần thứ nhất, từ vòng lặp thứ hai, chúng được thực hiện khi condition nhận giá trị True.
Ví dụ sau tính tổng của 5 số tự nhiên đầu tiên dùng cấu trúc do-while.
package vidu.chuong3;
class DoWhileDemo
{
 public static void main(String args[])
 {
  int a = 1, sum = 0;
  do{
   sum += a;
   a++;
  } while (a <= 5);
  System.out.println(“Sum of 1 to 5 is “ + sum);
 }
}
Biến a được khởi tạo với giá trị 1, sau đó nó vừa được dùng làm biến chạy (tăng lên 1 sau mỗi lần lặp) vừa được dùng để cộng dồn vào biến sum. Tại thời điểm kết thúc, chương trình sẽ in ra Sum of 1 to 5 is 15.
5 Vòng lặp for
Vòng lặp for cung cấp một dạng kết hợp tất cả các đặc điểm chung của tất cả các loại vòng lặp: giá trị khởi tạo của biến chạy, điều kiện dừng của vòng lặp và lệnh thay đổi giá trị của biến chạy.
Cú pháp:
for(initialization statements; condition; increment statements) 
{ 
action statements;

}
initialization statements: khởi tạo giá trị ban đầu cho các biến chạy, các lệnh khởi tạo được phân cách nhau bởi dấu phẩy và chỉ thực hiện duy nhất một lần vào thời điểm bắt đầu của vòng lặp.
condition:Biểu thức bool; vòng lặp sẽ tiếp tục cho đến khi nào điều kiện có giá trị False.
increment statements:Các câu lệnh thay đổi giá trị của biến chạy. Các lệnh này luôn được thực hiện sau mỗi lần thực hiện khối lệnh trong vòng lặp. Các lệnh phận biệt nhau bởi dấu phẩy.
Đoạn chương trình sau hiển thi tổng của 5 số đầu tiên dùng vòng lặp for.
package vidu.chuong3;
class ForDemo
{
 public static void main(String args[])
 {
  int sum = 0;
  for (int i = 1; i <= 5; i++)
   sum += i;
  System.out.println(“The sum is “ + sum);
 }
}
Ở ví dụ trên, i và sum là hai biến được gán các giá trị đầu là 1 và 0 tương ứng. Điều kiện được
kiểm tra và khi nó còn nhận giá trị True, câu lệnh tác động trong vòng lặp được thực hiện. Tiếp
theo giá trị của i được tăng lên 2 để tạo ra số chẵn tiếp theo. Một lần nữa, điều kiện lại được kiểm
tra và câu lệnh tác động lại được thực hiện. Sau năm vòng, i tăng lên 6, điều kiện trả về giá trị
False và vòng lặp kết thúc. Thông báo: The sum is 15 được hiển thị.

Wednesday, September 16, 2015

[Java] Kiến trúc chương trình xây dựng trên Java

1. Kiến trúc chương trình Java 
 Dạng cơ bản của một tập tin mã nguồn Java có cấu trúc như sau :
package packageName; // Khai báo tên gói, nếu có 
import java.awt.*;  // Khai báo tên thưviện sẵn có, nếu cần dùng 
class className   // Khai báo tên lớp 
{
 /* Đây là dòng ghi chú */
 int var;    // Khai báo biến 
 public void methodName() // Khai báo tên phương thức 
 {
  /* Phần thân của phương thức */
  statement(s); // Lệnh thực hiện 
 }
}

Một tệp mã nguồn Java có thể có ba phần chính:
• Phần khai báo tên gói (khối) bằng từ khoá package.
• Phần khai báo thư viện tham khảo bằng từ khoá import.
• Phần khai báo nội dung lớp bằng từ khoá class.
Khai báo Package
Package được dùng để đóng gói các lớp trong chương trình lại với nhau thành một khối. Đây là một cách hữu hiệu để lưu trữ các lớp gần giống nhau hoặc có cùng một module thành một khối thống nhất.
Cú pháp khai báo tên gói bằng từ khoá package:
package ;
Để đặt tên package trong chương trình, người ta có thể tiến hành như đặt tên thư mục trên ổ đĩa. Nghĩa là bắt dầu bằng tên có phạm vi lớn, cho đến các tên có phạm vi nhỏ, cuối cùng là tên các gói trực tiếp chứa các lớp. Phạm vi đặt tên gói, trên thực tế, được tiến hành theo thứ tự phạm vi lớn đến nhỏ như sau:
•  Tên tổ chức
•  Tên công ty
•  Tên dự án
•  Tên modul trong dự án
•  Tên các chức năng trong modul.
Ví dụ:
•  Tên miền của công ty là syz.com
•  Tên dự án là pro
•  Dự án có hai modul là mod1và mod2
•  Modul mod1 có hai chức năng là kết nối cơ sở dữ liệu connection và biểu diễn dữ liệu bean.
•  Modul mod2 có hai chức năng là giao tiếp interface và xử lí yêu cầu process.
Ưu điểm của package:
•  Cho phép nhóm các lớp vào với nhau thành các đơn vị nhỏ hơn. Việc thao tác trên các đơn vị khối sẽ gọn hơn thao tác trên một tập các lớp.
•  Tránh việc xung đột khi đặt tên lớp. Vì các lớp không cùng package thì có thể đặt tên trùng nhau. Khi số lượng lớp của chương trình quá lớn ta có thể tránh phải đặt tên khác nhau cho các lớp bằng cách đặt chúng vào các package khác nhau.
•  Cho phép bảo vệ các lớp. Khi chương trình lớn, việc chia nhỏ chương trình thành các package sẽ thuận lợi hơn cho việc quản lí và phát triển.
•  Tên gói còn được dùng để định danh lớp trong ứng dụng.
Lưu ý:
•  Dòng lệnh khai báo tên khối phải được đặt đầu tiên trong tện tin mã chương trình.
•  Chỉ được khai báo tối đa một tên khối đối với mỗi tệp mã nguồn Java.
•  Các tệp tin của các lớp nằm cùng gói ứng dụng phải được lưu trong cùng một thư mục (tên thư mục là tên khối) theo cấu trúc khối của dự án.
•  Tên khối nên đặt theo chữ thường vì tên khối sẽ là tên thư mục tương ứng trong ổ đĩa, tránh nhầm lẫn với tên các tệp tin là tên các lớp của chương trình.
•  Khi không phân chia chương trình thành khối (chương trình đơn giản), không cần thiết phải khai báo tên khối ở đầu chương trình.
Khai báo thư viện
Khai báo thư viện để chỉ ra những thư viện đã được định nghĩa sẵn mà chương trình sẽ tham khảo
tới. Cú pháp khai báo thư viện với từ khóa import như sau:
import ;
Java chuẩn cung cấp một số thư viện như sau:
•  java.lang: cung cấp các hàm thao tác trên các kiểu dữ liệu cơbản, xử lí lỗi và ngoại lệ, xử lí vào ra trên các thiết bị chuẩn như bàn phím và màn hình.
•  java.applet: cung cấp các hàm cho xây dựng các applet
•  java.awt: cung cấp các hàm cho xây dựng các ứng dụng đồ hoạ với các thành phần giao diện multi media (sẽ trình bày chi tiết trong Chương 6).
•  java.io: cung cấp các hàm xử lí vào/ra trên các thiêt bị chuẩn và các thiết bị ngoại vi.
•  java.util: cung cấp các hàm tiện ích trong xử lí liên quan đến các kiểu dữ liệu có cấu trúc như Date, Stack, Vector.
Ví dụ, nếu trong chương trình cần đến các thao tác chuyển kiểu đổi dữ liệu tường minh (từ kiểu string sang kiểu int), thì ta sẽphải tham khảo thư viện java.lang: import java.lang.*;
Lưu ý:
•  Nếu muốn khai báo tham khảo nhiều thư viện, phải khai báo tham khảo mỗi thư viện với một từ khóa import.
•  Nếu chỉ tham khảo một vài lớp trong một thư viện, nên chỉ rõ tham khảo lớp nào, thay vì phải khai báo tham khảo cả gói (bằng kí hiệu “*”) vì tham khảo cả gói sẽ tăng kích cỡ tệp tin class sau khi biên dịch.
•  Nếu không tham khảo thư viện nào, không cần thiết phải khai báo các tham khảo với từ khoá import.
Khai báo lớp
Phần thứ ba là phần khai báo lớp và nội dung của lớp, phần này luôn bắt buộc phải có đối với một tệp mã nguồn Java:
•  Khai báo tên lớp với từ khoá class.
•  Khái báo các thuộc tính của lớp.
•  Khai báo các phương thức của lớp
Chương trình Java đầu tiên
Chương trình sau đây cho phép hiển thị một thông điệp (Nằm trong tệp mã nguồn First.java):
package vidu.chuong3;
// Đây là chương trình “First.java” 
class First
{
 public static void main(String args[])
 {
  System.out.println(“Hello World”);
 }
}
Trong Java, tất cả mã lệnh đều phải được tổ chức vào trong một lớp nhất định. Do đó, mỗi tệp tin mã nguồn xác định ít nhất một lớp Java và tên tệp tin phải trùng với tên lớp. Java phân biệt chữ hoa và chữ thường, cho nên tên tập tin của chương trình trên phải trùng với tên lớp: First.java.
package vidu.chuong3;
Đây là dòng khai báo tên khối của chương trình, vì tên khối của chương trình được đặt theo hai
mức:
•  Mức thứ nhất là kiểu bài: ví dụ(vidu) hoặc bài tập (baitap).
•  Mức thứ hai là tên của chương: chuong3, chuong4, chuong5, chuong6
Vì đây là ví dụ, nằm ở chương 3 nên thuộc vào gói vidu.chuong3. Đồng thời, tệp tin First.java sẽ
nằm trong thưmục: ../vidu/chuong3/.
Chương trình này không tham khảo thư viện nào nên không cần lệnh import nào.
// Đây là chương trình “First.java”
Ký hiệu “// ” dùng để chú thích dòng lệnh. Trình biên dịch sẽ bỏ qua dòng chú thích này. Java hỗ trợ hai loại chú thích:
•  Loại chú thích trên một dòng, dùng “//”. Trình biên dịch sẽ bỏ qua nội dung bắt đầu từ kí
hiệu “//” cho đến hết dòng lệnh chứa nó.
•  Loại chú thích trên nhiều dòng có thể bắt đầu với “/*” và kết thúc với “*/”. Trình biên dịch sẽ bỏ qua nội dung nằm giữa hai kí hiệu này.
Dòng kế tiếp khai báo lớp có tên First: Bắt đầu với từ khóa class, kế đến là tên lớp class First
Một định nghĩa lớp nằm trọn vẹn giữa hai ngoặc móc mở“{“ và đóng “}”. Các ngoặc này đánh dấu bắt đầu và kết thúc một khối lệnh.
public static void main(String args[ ])
Đây là phương thức chính, từ đây chương trình bắt đầu việc thực thi của mình. Tất cả các ứng dụng java đều sử dụng một phương thức main này.
•  từ khóa public là một chỉ định truy xuất. Nó cho biết thành viên của lớp có thể được truy xuất từ bất cứ đâu trong chương trình.
•  từ khóa static cho phép main được gọi tới mà không cần tạo ra một thể hiện (instance) của lớp. Nó không phụ thuộc vào các thể hiện của lớp được tạo ra.
•  từ khóa void thông báo cho máy tính biết rằng phương thức sẽ không trả lại bất cứ giá trị nào khi thực thi chương trình.
•  String args[]là tham số dùng trong phương thức main. Khi không có một thông tin nào được chuyển vào main, phương thức được thực hiện với các dữ liệu rỗng – không có gì trong dấu ngoặc đơn.
•  System.out.println(“Hello World”); Dòng lệnh này hiển thị chuỗi “Hello World” trên màn hình. Lệnh println()cho phép hiển thị chuỗi được truyền vào lên màn hình.