負數的進位轉換程序:java判斷正數轉負數

Java中有很多內容在開發項目的過程中並不常用,但是卻是很重要的部分,為了避免忘記,今天重新溫習了一遍Java中的重點和難點,藉此機會記錄一下方便以後查找。

本文主要分為以下幾個部分:

1.進位的相互轉換

2.Java中位運算符的解釋和運用

3.Java數組中常用的排序演算法分析

4.Java中折半查找方法的分析和運用

5.Java中對象的初始化過程

6.Java抽象類在模板方法模式中的運用

7.Java多線程的難點和設計多線程程序時需要注意的問題

8.Java中集合框架運用時需要注意的問題

9.Java中IO難點和重點的分析

10.Java網路編程的分析和運用

11.Java中常用正則表達式的運用和技巧

第一部分:進位的相互轉換

1.十進位和二進位的相互轉換

十進位轉二進位:

int num = 102;
StringBuffer sb = new StringBuffer();
while(num >= 1) {
    sb.append(num%2);
    num = (int) (num / 2);  
}
System.out.println(sb.reverse());

二進位轉十進位:

String binaryStr = "1100110";
int num = 0;
for (int i = 0; i < binaryStr.length(); i++){
    num += Integer.parseInt(String.valueOf(binaryStr.charAt(binaryStr.length() - 1 - i))) << i;
}
System.out.println(num);

第二部分:Java中位運算符的解釋和運用

Java中一共有7個位運算符分別是<<、>>、&、|、^、~、>>>

1.「<<」–左移運算符,參與左移運算的數字乘以2的左移位數次方,例如3<<2=3*22

2.「>>」–右移運算符,參與右移運算的數字除以2的右移位數次方,例如3>>2=3/22

3.「&」 –與運算符,參與與運算的兩個數字的二進位等位都為1時結果值的該位為1,其餘情況為0,例如3&2=0011&0010=0010,與運算符和「>>>」運算符結合可以實現十進位轉十六進位的功能,num&15 -> num>>>4,這樣一組運算就能得到一個十六進位位,再將超過10的通過(num-10)+’A’轉換為十六進位位

4.「|」 –或運算符,參與或運算的兩個數字的二進位等位至少有一個為1時結果值的該位為1,其餘情況為0,例如3|2=0011|0010=0011

5.「^」 –異或運算符,參與異或運算的兩個數字的二進位等位如果不相同則為1,相同則為0,一個數字異或同一個數字兩次則等於原數字。其中一個應用是在不使用第三個變數的情況下交換兩個×××變數的值。

int n = 4,m = 6;
//此時n = n ^ m的值
n = n ^ m; 

//此時m = n ^ m,因為上句代碼執行後n = n ^ m,所以這裡m = n ^ m = n ^ m ^ m = n(這裡的m = n中的n = 4)
m = n ^ m;

//此時m = n,n = n ^ m , 所以n = n ^ m = n ^ m ^ n=m(這裡的n = m中的m = 6)
n = n ^ m;

6.「~」 –取反運算符,參與取反運算的數字的所有二進位位都取相反的值,0變成1,1變成0,因為一個正數的負數或者一個負數的正數等於它取反然後加1,所以一個數取反則等於該數乘以-1然後減去1

7.「>>>」 –無符號右移,高位補零,功能和右移類似

第三部分:Java數組中常用的排序演算法

1.選擇排序

int[] attr = {3,6,5,85,2,44,1,46,67,0,45,4,134,123,112};

for(int x = 0;x < attr.length() - 1, x++) {
    for(int y = x + 1; y < attr.length(); y++) {
        if(attr[x]<attr[y]) {
            attr[x] = attr[x] ^ attr[y];
            attr[y] = attr[x] ^ attr[y];
            attr[x] = attr[x] ^ attr[y];
        }
    }
}

for(int i in attr) {
    System.out.print(i + " ");
}

2.冒泡排序

int[] attr = {3,6,5,85,2,44,1,46,67,0,45,4,134,123,112};

for(int x = attr.length() - 1;x >= 0; x--) {
    for(int y = 0; y < x;y++) {
        if(attr[y] < attr[y + 1]) {
            attr[y] = attr[y] ^ attr[y + 1];
            attr[x] = attr[y] ^ attr[y + 1];
            attr[y] = attr[y] ^ attr[y + 1];
        }
    }
}

for(int i in attr) {
    System.out.print(i + " ");
}

第四部分:Java中折半查找方法的分析和運用

折半查找的原理是先將數組排序(從小到大,如果是從大到小則需要一些改變),然後找到數組中的中間數,然後把中間數和需要查找的數進行比較,如果需要查找的數小於中間數則將最大索引賦值為中間結果索引+1,反之則把最小索引賦值為中間結果-1。代碼如下:

int[] attr = {3,6,5,85,2,44,1,46,67,0,45,4,134,123,112};

int min = 0;
int max = attr.length();
int mid = (int) (min + max) / 2;

Arrays.sort(attr);

int key = 67;
int keyIndex = -1;
while(min <= max) {
    
    if(key < attr[mid]) {
        max = mid + 1;
    } else if(key > attr[mid]) {
        min = mid - 1;
    } else {
        keyIndex = mid;
        break;
    }
    
    mid = (int) (min + max) / 2;
}

if(keyIndex != -1) {
    System.out.println(attr[mid]);
}

第五部分:Java中對象的初始化過程

  1. 初始化靜態代碼塊
  2. 初始化屬性默認值
  3. 初始化屬性顯示設置值
  4. 初始化構造代碼塊
  5. 初始化構造函數

第六部分:Java抽象類在模板方法模式中的運用

這裡舉一個簡單的示例代碼來說明,代碼如下:

//首先聲明一個抽象類,這個抽象類的作用是計算一段代碼的執行時間
public abstract class GetTime {
    public final void getDoWorkTime() {
        int start = System.currentTimeMillis();
        doWork();
        int end = System.currentTimeMillis();
        
        System.out.println("工作時間:" + (start - end));
    }
    
    public abstract void doWork();
}

//聲明一個GetTime類的子類,並實現doWork方法
public class SubGetTime extends GetTime {
    @Override
    public void doWork() {
        System.out.println("做一些工作");
    }
}

public class Test {
    public static void main(String[] args) {
        SubGetTime getTime = new SubGetTime();
        getTime.getDoWorkTime();
    }
}

//這裡的doWork方法聲明為抽象方法,然後交給子類去實現需要做的工作,這種方式就是模板方法模式,這是設計模式中行為模式中的一種

第七部分:Java多線程的難點和設計多線程程序時需要注意的問題

Java多線程中的難點和重點主要是線程安全的問題,這裡就主要說一下線程安全的問題,因為在JDK1.5後Java引入了Lock和Condition來代替synchronized、wait和notify,所以這裡分兩種情況來討論。

首先在Java中創建線程的方式有兩種,第一種是繼承Thread類然後複寫run方法,第二種方式是實現Runable介面並實現run方法。

繼承Thread:

public class SaveMoney extends Thread {
    @Override
    public void run() {
        System.out.println("存錢");
    }
}
public class GetMoney extends Thread {
    @Override
    public void run() {
        System.out.println("取錢");
    }
}
public class BankTest {
    public static void main(String[] args) {
        SaveMoney saveMoneyThread = new SaveMoney();
        GetMoney  getMoneyThread  = new GetMoney();
        saveMoneyThread.start();//啟動線程,這裡如果調用run是執行run方法不是啟動線程,需要注意
        getMoneyThread.start();
    }
}

實現Runable介面:

public class SaveMoney implements Runable {
    public void run() {
        System.out.println("存錢");
    }
}
public class GetMoney implements Runable {
    public void run() {
        System.out.println("取錢");
    }
}
public class BankTest {
    public static void main(String[] args) {
        new Thread(new SaveMoney()).start();//啟動線程,這裡如果調用run是執行run方法不是啟動線程,需要注意
        new Thread(new GetMoney()).start();
    }
}

下面就在JDK1.5之前和JDK1.5之後兩種情況下結合銀行取錢和存錢的例子來說明線程同步的問題

JDK1.5之前:

//首先創建一個用戶帳戶類
public class BankAccont {
    
    private String accontName = "";
    private Double totalMoney = 0d;
    
    public BankAccont(String accontName, Double initMoney) {
        this.accontName = accontName;
        this.totalMoney = initMoney;
    }
    
    public void saveMoney(Double money) {
        this.totalMoney += money;
        System.out.println("存了" + money + "塊錢");
    }
    
    public void getMoney(Double money) {
        this.totalMoney -= money;
        System.out.println("取了" + money + "塊錢");
    }
    
    public String toString() {
        System.out.println(this.accontName + "總共還有" + this.totalMoney + "元人民幣");
    }
}

//分別創建存錢和取錢的線程,使用實現Runable介面的方式這種方式可以輕鬆的讓不同的線程執行相同的任務,除非程序員打算修改或增強類的基本行為,否則不應為該類(Thread)創建子類
public class SavaMoney implements Runable {
    private BankAccont accont = null;
    public SaveMoney(BankAccont accont) {
        this.accont = accont;
    }
    public void run() {
             //這裡使用同一個鎖進行同步
             synchronized(BankAccont.class) {
            while(true) {
              this.accont.saveMoney(100);
          }
       }
    }
} 
public class GetMoney implements Runable {
    private BankAccont accont = null;
    public GetMoney(BankAccont accont) {
        this.accont = accont;
    }
    public void run() {
            //這裡使用同一個鎖進行同步
            synchronized(BankAccont.class) {
            while(true) {
                this.accont.getMoney(100);
            }
        }
    }
}
public class BankTest {
    public static void main(String[] args) {
        BankAccont accont = new BankAccont("張三", 1000);
        
        new Thread(new SaveMoney(accont)).start();
        new Thread(new GetMoney(accont)).start();
        
        accont.toString();
    }
}

JDK1.5之後:

//首先創建一個用戶帳戶類
public class BankAccont {
    
    private String accontName = "";
    private Double totalMoney = 0d;
    
    private final Lock lock = new RentrantLock();
    private final Condition condition_save = lock.newCondition();
    private final Condition condition_get  = lock.newCondition();
    
    public BankAccont(String accontName, Double initMoney) {
        this.accontName = accontName;
        this.totalMoney = initMoney;
    }
    
    public void saveMoney(Double money) {
        lock.lock();
        condition_get.await();//這裡引用不合適,只是一個示例
        this.totalMoney += money;
        System.out.println("存了" + money + "塊錢");
        condition_get.signal();//這裡引用不合適,只是一個示例
        lock.unlock();
    }
    
    public void getMoney(Double money) {
        lock.lock();
        condition_save.await();//這裡引用不合適,只是一個示例
        this.totalMoney -= money;
        System.out.println("取了" + money + "塊錢");
        condition_save.signal();//這裡引用不合適,只是一個示例
        lock.unlock();
    }
    
    public String toString() {
        System.out.println(this.accontName + "總共還有" + this.totalMoney + "元人民幣");
    }
}

//分別創建存錢和取錢的線程,使用實現Runable介面的方式這種方式可以輕鬆的讓不同的線程執行相同的任務,除非程序員打算修改或增強類的基本行為,否則不應為該類(Thread)創建子類
public class SavaMoney implements Runable {
    private BankAccont accont = null;
    public SaveMoney(BankAccont accont) {
        this.accont = accont;
    }
    public void run() {
            while(true) {
              this.accont.saveMoney(100);
          }
    }
} 
public class GetMoney implements Runable {
    private BankAccont accont = null;
    public GetMoney(BankAccont accont) {
        this.accont = accont;
    }
    public void run() {
            while(true) {
                this.accont.getMoney(100);
            }
    }
}
public class BankTest {
    public static void main(String[] args) {
        BankAccont accont = new BankAccont("張三", 1000);
        
        new Thread(new SaveMoney(accont)).start();
        new Thread(new GetMoney(accont)).start();
        
        accont.toString();
    }
}

以上只是一個簡單的示例,需要根據需要進行修改。在設計多線程程序的時候需要多考慮線程同步的問題(線程安全),在多線程中還有一個問題就是Java中有哪些線程安全的集合?

Java中線程安全的集合分別是Vector(向量,已經不常用了)、HashTable、Enumeration(枚舉),除了這幾個其餘都為線程不安全集合。StringBuffer和StringBuider的差別也是StringBuffer為線程安全,StringBuider為線程不安全。

Java多線程相關的問題,暫時只想到這些,再想起的時候再補充。

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/223433.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-09 14:20
下一篇 2024-12-09 14:20

相關推薦

發表回復

登錄後才能評論