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] Hàm Join trong Java

Hàm Join được sử dụng để giữ cho quá trình thực thi của hàm đang chạy không bị gián đoạn bởi các thread khác, nói một cách khác nếu một thead đang chạy các thread khác sẽ phải chờ cho đến khi thread đó thực thi xong.
Tạo sao lại sử dụng hàm Join.
Trong một chương trình Java thường có nhiều hơn một thread,trong đó có main thread - có chức năng khởi tạo và kích hoạt để chạy các thread khác, tuy nhiên các main thread không đảm bảo các thread thực thi và kết thúc theo đúng thứ tự mà chúng đã được khởi chạy. Hãy xem ví dụ sau:
1. Khi không sử dụng hàm Join.
Ở đây có 3 thread th1, th2, th3. Mặc dù các thread được khởi chạy theo thứ tự th1>th2>th3 nhưng kết thúc thực thi của 3 thread trên không theo thứ tự th1>th2>th3. Ở mỗi thời điển chạy chương trình có thể nhận được các kết quả khác nhau.
public class JoinExample {
 public static void main(String[]args){
  Thread th1 = new Thread(new MyThread(),"th1");
  Thread th2 = new Thread(new MyThread(),"th2");
  Thread th3 = new Thread(new MyThread(),"th3");
  th1.start();
  th2.start();
  th3.start();
 }
}
class MyThread implements Runnable {
 public void run() {
  Thread t = Thread.currentThread();
  System.out.println("Bắt đầu thread: " + t.getName());
  try{
   Thread.sleep(4000);
  }catch(InterruptedException e){
   e.printStackTrace();
  }
  System.out.println("Kết thúc thread:" + t.getName());
 }
}
Output:
Bắt đầu thread: th1
Bắt đầu thread: th3
Bắt đầu thread: th2
Kết thúc thread:th3
Kết thúc thread:th1
Kết thúc thread:th2
2. Khi sử dụng hàm Join
Câu hỏi đưa ra là: Làm thế nào để các thread thực thi và kết thúc theo đúng thứ tự mà chúng được khởi chạy. Câu trả lời là: Sử dụng hàm Join sẵn có của Java. Giả sử thứ tự của các thread là: thread1 chạy trước, sau đó là thread2, thread3 chạy sau cùng.
Chương trình cài đặt sử dụng hàm Join như sau:
public class JoinExample {
 public static void main(String[]args){
  Thread th1 = new Thread(new MyThread(),"th1");
  Thread th2 = new Thread(new MyThread(),"th2");
  Thread th3 = new Thread(new MyThread(),"th3");
  //khởi chạy thread 1.
  th1.start();
  try {
   th1.join();
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  //khởi chạy thread 2.
  th2.start();
  try {
   th2.join();
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  //khởi chạy thread 3.
  th3.start();
  try {
   th3.join();
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }
}
class MyThread implements Runnable {
 public void run() {
  Thread t = Thread.currentThread();
  System.out.println("Bắt đầu thread: " + t.getName());
  try{
   Thread.sleep(4000);
  }catch(InterruptedException e){
   e.printStackTrace();
  }
  System.out.println("Kết thúc thread:" + t.getName());
 }
}
Khi chạy chương trình trên, ta sẽ thấy kết quả in ra mà hình theo thứ tự  th1>th2>th3
Output:
Bắt đầu thread: th1
Kết thúc thread:th1
Bắt đầu thread: th2
Kết thúc thread:th2
Bắt đầu thread: th3
Kết thúc thread:th3
Khi so sánh với chương trình cài đặt không sử dụng hàm Join, thread2, thread3, chưa khởi chạy ngay được gọi bằng lệnh th2.start(), th3.start() , thead2 và thread3 đã đợi cho đến khi thread1 thực thi xong mới khởi chạy. Tương tự khi thread2 chạy thì thread3 vẫn phải đợi cho đến khi thread2 thực thi xong. Do đó mà kết quả in ra màn hình theo đúng thứ tự th1>th2>th3 mà chúng đã được khởi chạy.

[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.