Java 9至12的新功能(第三集)《G1 GC》

《這一回的內容會對於新手比較複雜。儘管很多編程新手都聽過垃圾回收(Garbage Collection或GC)的概念,但通常中級程序員才會比較深入地探索這概念。

雖然GC的背後運作原理是比較複雜,但畢竟它是一個非常重要的概念,它存在是因為在一個程式有很多的Object都是臨時製造的,而很多Object用完了之後就可以被刪除(就好像你硬碟有很多文檔都可以用完之後被刪除),從而騰空RAM記憶體的一些空間。

有很多科技企業都非常注重研究一些方法令一個大型的程式去盡量減少使用RAM,所以我建議新手也可開始學習GC。

(我未來可能會寫帖子講解一下GC的基本概念,但這一回我會跳過GC的基本概念)》

雖然G1 GC已於Java 7推出的時候面世,但到了Java 9才成為JVM預設的GC。

使用G1 GC

想享用G1 GC的話就會在VM options加–XX:+UseG1GC flag

G1 GC的架構

O = Old
S = Survivor
E = Eden
U = Unassigned

G1 GC的架構就是它不會像傳統的CMS GC那樣分為3個heaps,而是分為不同的regions,每個region都可以為2MB到32MB的面積不等,目的就是要減短GC進行的時間。

CMS GC需時長的原因正正是因為它要清理垃圾的時候,它要掃整個heap,將垃圾從Old傳送到去Survivor,再從Survivor傳到Eden,但是G1 GC的速度比較快就在於它可以挑選一些細小的regions掃,不必一次掃整個GC。

Old GC – Concurrent Mark & Sweep (CMS) GC

為什麼擁有很多細小的region可以提升清理垃圾的速度呢?

如果GC想騰空出記憶體的話,它就會挑選一些比較多垃圾的regions去騰空。譬如region A是一個2MB的Eden Space region,它當中有89%都是可丟棄的垃圾,那G1 GC就可以很快地將剩餘11%的live reference傳到鄰近region B的survivor space,而不需像CMS GC那般每次想騰空記憶體的時候都掃整個Eden space(一般的Eden space可以被設為64MB或更大),你每次掃64MB的空間就會花費更長的時間(相比起掃G1 GC的2MB region)。

當G1 GC一個region擁有100%垃圾的時候

但是G1 GC最理想的情況就是當一個region全部都是100%垃圾,G1 GC就可以直接把它垃圾抗直接變為Unassigned,這就會非常省時。當一個region變為Unassigned的時候,那個空間就是被騰空出來,令將來的live references倒進去。

相反,CMS GC就不可以這樣挑選一個擁有100%垃圾的region出來,除非你整個Young space都滿了。但Young space滿了就代表你JVM不夠記憶體去容納更多的live references,在執行大程式的時候,這是十分危險的。若JVM每次Young space 100%滿了才開始清理的話就會影響你Java程式本身產生live references的速度,足以令你的Java程式運行變慢。

最新消息和分析:英國政府將宣布把外勞薪酬門檻從£30000調低到£25600

《最新消息和分析:英國政府將宣布把外勞薪酬門檻從£30000調低到£25600,意味著更多的留學生,打工度假及移民英國人士可以赴英或留英工作 》 https://www.bbc.co.uk/news/uk-politics-51430811

有趣的是,英國大學生剛畢業的年薪一般是£20000至£30000,倫敦則高一點。

若把下限從£30000調低到£25500,這意味著很多留學生畢業後或許可以留英工作,特別是這幾門專業平均都是£25500左右:

• Social Work(剛畢業平均薪酬為£25,111)
• Nursing(剛畢業平均薪酬為£25,285)
• Geology(剛畢業平均薪酬為£26,679)
• Civil Engineering(剛畢業平均薪酬為£26,882)
• Building(剛畢業平均薪酬為£25,079)
• Veterinary Medicine(剛畢業平均薪酬為£28,277)
• Russian & East European Languages(剛畢業平均薪酬為£24,191)
• Physics & Astronomy(剛畢業平均薪酬為£26,731)
• Philosophy(剛畢業平均薪酬為£ 23,521)
• Materials Technology(剛畢業平均薪酬為£23,080)

直到現在,通常是Big4和投行才會批發工作簽證給畢業生,前者就是因為它是從超級大企業,後者就是因為它的畢業薪酬遠高於£30000。

這政策調整可能會改變英國的勞工市場架構,特別是為脫歐之後彌補東歐勞工的短缺。2016脫歐公投後,很多東歐人都離開英國了,但因為很多東歐人都是來英國從事低技術的工種,所以這其實就讓英國本土的低技術勞工的工資漲了。但也有高技術的東歐人如從事程序編碼員都離開英國了,所以企業都嘆難招聘人才,因此英國一般的企業都不想英國硬脫歐(Hard Brexit),現在英國政府不會硬脫歐對他們也是一件好事。

返回正題,我相信很多英國大中小企業都會歡迎政府把薪酬門檻調低,令他們招聘人才的過程容易點。小篇相信NHS是最受惠的企業,畢竟NHS長期已經依賴外來的勞工(包括很多的東歐勞工)來填補英國本土的職位空缺了。

小篇則會用拭目以待的眼光看待英國的其他大企業如Sky TV,BBC會不會因為這政策改變而開放外國留學生去申報他們的graduate scheme(類似培管生計劃)。

再加上英國政府早前公佈的Post-work Study Visa (PSW)讓留學生可以畢業後留英2年找工作,大家是不是覺得在英國畢業後再找工作會輕鬆點呢?

資料來源:

https://www.bbc.co.uk/news/uk-politics-51430811

https://www.gov.uk/government/news/uk-announces-2-year-post-study-work-visa-for-international-students

畢業生薪酬列表:

https://www.thecompleteuniversityguide.co.uk/careers/what-do-graduates-do-and-earn/starting-salaries-–-do-graduates-earn-more

Java 9至12的新功能(第二集)《Modules》

我這回會說一下Java 9的Modules,它屬於架構性的功能(Architecture-level features):

Java 9 Modules是什麽,跟Python package又有什麼關係?

Java Modules就是好像Python的packages,其最主要的功能就是export跟import一些其他modules板塊的inter-dependencies,下圖就是一個簡單Java Modules的例子,你會看到有於package “org.codefx.demo.jpms”外面會附上一個”module-info.java” –> 這檔案是於Java 8或之前是沒有的:

而”module-info.java”就是這樣寫的:

module org.codefx.demo.jpms_hello_world {
    // this module only needs types from the base module 'java.base';
    // because every Java module needs 'java.base', it is not necessary
    // to explicitly require it - I do it nonetheless for demo purposes
    requires java.base;
    // this export makes little sense for the application,
    // but once again, I do this for demo purposes
    exports org.codefx.demo.jpms;
}

這就跟Python裡面Packages的__init__.py檔案很相似:

__init__.py就是這樣:

 # __init__.py
from .foo import foo_func
from .bar import bar_func
from .baz import baz_func

Java 9 Modules好處

那為什麼我們要用Modules呢,而Java 9 Modules又有什麼好處呢?

  • Java Development Kit (JDK)所存的一切dependencies太多了,未必所有的小型裝置都需要JDK的一切dependencies。尤其是Java 8新增了不少功能如Stream API,default methods in interfaces,令JDK都變大了
  • Modules增加了package的encapsulation。於Java 8或以前你的一個public method就可以讓所有packages存取你的class,但Java 9的Modules就可以讓你調整你個別package的能見度visibility。
  • 鞏固了Single Responsibility Principle(SRP)。在軟件設計的SOLID principles內,SRP是非常重要的環節 – 你現在看到JDK 8附帶的Stream interface已經有很多不同的method,非常多line of code,可以算是God class,我們就是要採用SRP去避免建造God class。

Java 9 Modules壞處

筆者好奇的是,我還是沒有看過網上對Java 9 Modules有什麼負評的,我則可以想到幾個壞處:

  • Missing classes or interfaces
    • Java 9 Modules的最大不好處就是要經常想有什麼dependencies需要import跟export,但Java 8就不用想需要那個dependencies;很多時候用IntelliJ或eclipse的auto-import功能就可以解決dependencies的問題了。 😂
  • Version mismatch between different JAR files
    • 如果你的package跟module用Java 9,但你又想採用別人用Java 12建設的 package跟module ,這有機會導致你跟他的 package跟module產生互相不兼容問題。

Java 9 模塊Modules例子:JDK 9內設的java.base

JDK9提供的模塊的例子就是java.base,當中會export java.lang.annotation(為了TestNG跟JUnit的unit testing)和java.lang.reflect(為了Java的Reflection功能)跟java.io(為了read/write from disk)

java –describe-module

你也可以在Windows的command prompt或Linux的terminal內輸入–describe-module看看該module是requires什麼,export什麼。

但注意要先define Java $PATH或%PATH%才能夠在command prompt或terminal執行java –describe-module java.sql

 $ java --describe-module java.sql
> java.sql@9
> exports java.sql
> exports javax.sql
> exports javax.transaction.xa
> requires java.logging transitive
> requires java.base mandated
> requires java.xml transitive> uses java.sql.Driver

Java 9 Modules的其他關鍵詞

我們暫時只探討了requires和exports這兩個關鍵詞,其實Java 9 Modules還有其他的關鍵詞:

exports, module, open, opens, provides, requires, uses, with

下一篇持續…

Java 9至12的一些新功能(第一集)

《怎麼樣學Programming篇》最近我於公司做了一個短短的簡報(technical presentation)主要講述Java 9至12的新功能,有很多幹Java的同事都覺得蠻好奇的,因為畢竟我們公司很多的系統還停留於Java 8。。。

身為一名Java軟件工程師,我一直需要提升我的技能。你越懂一種編碼語言的新功能就可以在求職市場上凸顯自己的優勢。譬如我最初是於2013年在大學開始學Java的,那時候還是Java 7盛行的年代,跟本沒有Functional Programming的性能。Functional programming的性能是於Java 8開始才有的。

就算Java 8最終於2014年推出了,但是2014至2016年期間很多企業跟本也還沒用Java 8,直到2016開始企業才開始慢慢地升級用Java 8,所以2014至2016年便是『空窗期』 – 面試考官通常不會需要你懂Java 8,只是“nice to have”而已,你若能描述Java 8新功能的一些細節便會於面試大大加分。

同樣地,很多Java工程師也不懂2019年推出Java 12和Java 13的新功能。你能夠掌握到Java 12和13的新功能便能於面試加分。

你越懂一種編碼語言的新功能就可以在求職市場上凸顯自己的優勢。

這次我會講一些新Java語法的功能(Syntax-level features),我於下面並加插了自己的中文演繹(我為公司做的簡報是沒有這些加插的演繹),下集會提及一些新Java比較複雜的架構性能(Architecture-level features)。

Syntax-level features:

  • Enhanced Stream API (Java 9)
  • Java REPL (Java 9)
  • New Factory Methods for Collections (Java 9)
  • Var keyword (Java 10)
  • Switch-case statement (Java 12)

Architecture-level features:

  • Modules (Java 9)
  • Garbage Collector Z (Java 11)

Enhanced Stream API (Java 9)

『有使用Java 8的人都知道Stream API是於Java 8才推出的,它的目的主要是為了簡化長的代碼,譬如說”filter()”和”map()”功能就省掉一個for-loop或while-loop,Stream API另外也會提升代碼的閱讀簡易度(code readability)。

Java 9則於Stream API增加了一些功能如takeWhile(),DropWhile(),iterate(),ofNullable(),主要也是為了簡化代碼,取代loop。』

1. takeWhile() method

Syntax

 default Stream<T> takeWhile(Predicate<? super T> predicate)  

Example

Stream<Integer> stream = Stream.of(1,2,4,5,3,6,7,8,9,10) 
stream.takeWhile(x -> x < 4).forEach(a -> System.out.println(a))

Output

1
2

2. dropWhile() method

Syntax

 default Stream<T> dropWhile(Predicate<? super T> predicate)  

Example

Stream<Integer> stream = Stream.of(1,2,4,5,3,6,7,8,9,10) 
stream.dropWhile(x -> x < 4).forEach(a -> System.out.print(a))

Output

 453678910

3. iterate() method

Syntax

static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next) 

Example

 IntStream.iterate(2, x -> x < 20, x -> x * x).forEach(System.out::println) 

Output

2
4
16

4. ofNullable() method

Syntax

 static <T> Stream<T> ofNullable (T t) 

Explanation

It helps to handle the null stream and NullPointerException (NPE). Java 8 only has Stream.of() – it cannot handle null stream and NPE.

『新手一定要知道怎麼樣處理exceptions,因為不正確處理exceptions會導致整個程式癱瘓。香港某一個大型超市的線上購網的主頁也最近出現了NullPointerException 😂,令顧客無法線上購物。』

Example

 Stream<String> value = Stream.ofNullable(null);
value.forEach(System.out::println);

Output

{NOTHING}

Read-Eval-Print-Loop or REPL (Java 9)

『簡單來說,REPL就好像Linux bash script,可以給你在terminal寫一點代碼並顯示出一些結果。』

REPL uses a new feature JShell. With JShell, you can:

$ bash ./scripts/run.sh |  Welcome to JShell -- Version 0.710
|  Type /help for help

-> Math.sqrt( 144.0f );
|  Expression value is: 12.0
|    assigned to temporary variable $1 of type double

-> $1 + 100;
|  Expression value is: 112.0
|    assigned to temporary variable $2 of type double

New Factory Methods for Collections (Java 9)

一句而言,Java 9簡化了初始List,Set和Map的代碼。Java 8或以前用new ArrayList<>(),new HashSet<>()或new HashMap<>(),現在用List.of(),Set.of(),或Map.of()則可以建立List,Set和Map了,但一次只能最多建立10個物件。

這樣的功能當然是好事,但是令我感到無奈的是List class的implementation有一些不能refactor的redundant code:

public class List<A> extends AbstractCollection<A> implements java.util.List<A> {
...
public static <A> List<A> of(A x1) { return new List<>(x1, List.nil()); }
public static <A> List<A> of(A x1, A x2) { return new List<>(x1, of(x2)); }
public static <A> List<A> of(A x1, A x2, A x3) { return new List<>(x1, of(x2, x3)); }
...
}

其實上面的代碼被寫成下方便可以了:

public class List<A> extends AbstractCollection<A> implements java.util.List<A> {
...

public static <A> List<A> of(A x1, A x2, A x3, A... rest) {

return new List<>(x1, new List<>(x2, new List<>(x3, from(rest))));
}
...
}

1. Factory method for List

Before Java 9:

 public static void main(String[] args) {
    List<String> list1 = new ArrayList<>();
    list1.add("Java");
    list1.add("JavaFX");
}

Since Java 9, List.of() can store up to 10 items:

public static void main(String[] args) {
          List<String> list = List.of("Java","JavaFX");  
}

2. Factory method for Set

Before Java 9:

 public static void main(String[] args) {
    Set<String> set1 = new HashSet<>();
    set.add("Java");
    set.add("JavaFX");
}

Since Java 9, Set.of() can store up to 10 items:

public static void main(String[] args) {
          Set<String> set = Set.of("Java","JavaFX");  
}

3. Factory method for Map

Before Java 9:

 public static void main(String[] args) {  
    Map<Integer,String> integerString = new HashMap<Integer,String>();
    integerString.put(101, "JavaFX");
    integerString.put(102, "Hibernate");
}

Since Java 9, Map.of() can store up to 10 items, but does not allow null keys nor null values.

public static void main(String[] args) {
        Map<Integer,String> map = Map.of(101,"JavaFX",102,"Hibernate");
}

Var keyword (Java 10)

Before Java 10

 String greeting = "Hello World"; ArrayList<String> messages = new ArrayList<String>(); 
messages.add(greeting); 
Stream<String> stream = messages.stream();

Since Java 10

 var greeting = "Hello World";var messages = new ArrayList<String>();
messages.add(greeting);
var stream = messages.stream();

Things to note:

  • “var” can only be used in local variables, not in instance/global variables
  • “var” must be declared & initialized, otherwise compiler error

Usage of Var

 public class VarKeyword {
var stuff1 = 123; // compiler error

public static void main(String[] args) {
    var stuff2 = "asdf";
    while(true) {
        var stuff3 = "wefew";
        break;
    }
    var stuff4 = 21342;
}
}

Switch-case statement (Java 12)

Basics:

Before Java 12

 int numLetters;switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
numLetters = 6;
break;
case TUESDAY:
numLetters = 7;
break;
default:
throw new IllegalStateException("Huh? " + day);
}

Since Java 12

 int numLetters = switch (day) {case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
default -> throw new IllegalStateException("Huh? " + day);
};

“Breaks”:

Before Java 12

 int numLetters;switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
numLetters = 6;
break;
case TUESDAY:
numLetters = 7;
break;
default:
throw new IllegalStateException("Huh? " + day);
}

Since Java 12

 final int integer = 1;  System.out.println("Switch Expression with Colons/Breaks:");  
final String numericString =  
      switch (integer)  
      {  
         case 1 :  
            break "uno";  
         case 2 :  
            break "dos";  
         case 3 :  
            break "tres";  
         default :  
            break "N/A";  
      }; 

Additional note

新舊的switch-case statement不能互相兼容。Old and New switch-case statements cannot be mixed, below won’t work:

  final int integer = 3;
   String numericString;  
   switch(integer)  
   {  
      case 1 :  
         numericString = "one";  
         break;  // old switch-case syntax
      case 2 -> numericString = "two";  // new switch-case syntax
      default -> numericString = "N/A";  
   }  
   return numericString; 

下一篇持續…

《暑假實習篇》9項建議讓你得到投資銀行的final round interview終極面試

跟許多倫敦帝國理工學院Imperial College的學生一樣,筆者還唸year 2大二的時候就申報了不同投行的Sales & Trading的summer internship暑假實習計劃。從申報到拿到面試機會的過程 感覺就像玩電子遊戲一樣,要時刻裝備自己過關斬將。

一般來說,你填完了申報工作的表格後便會有線上檢測,過了之後就可能有面試機會。

為了備戰,有些倫敦帝國理工學院學生還會於校內24小時開放的圖書館操練線上檢測的試題(online competency reasoning test)。

儘管筆者經過屢次的面試失敗,筆者也可以學到了面試的技巧,方便應付其他公司的面試。最後,我也拿到了幾家投行Trading的final round interview,當中包括野村證卷。

從申報到拿到面試機會的過程 感覺就像玩電子遊戲一樣,要時刻裝備自己過關斬將。

以下是筆者的9個建議讓你增加成功率拿到投行的final round interview:

  • 有些投行的申報程序比其他的簡單。一般投行的網申程序都需要你填2至3篇200字作文,那些作文問題總會是what was your most difficult situation in life and how you overcame it?或者why do you want to work for bank x but not bank y? show me one time in which you demonstrated leadership skills?但是有少量投行不會問這些問題,你直接交上CV和cover letter便可以了(Cxxxxx Sxxxxx和Mxxxxx Sxxxxxx都不用作文)
  • Phone interview電話面試前應該把CV簡歷和一份預備好的Q&A問答拿出來;那篇Q&A問答就包含了幾條普遍面試的試題,如”explain one time when you overcome obstacles despite faced tight deadline”,你就寫出你有一次怎麼樣於短時間內完成了一些大學作業或處理一些私人事情
  • 簡歷CV的長度應保持於2頁內(英國標準)或1頁內(美國標準),盡可能提及你的金融相關的經驗(譬如筆者曾於校內參加了Imperial College Investment Club,我就寫以前每兩個星期都跟幾個隊友見面,並討論下應該投資什麼股票或外匯,之後用網上交易平台去買賣模擬的股票或外匯)
  • 進入面對面 面試face to face interview的時候盡可能挺直胸膛 以便創造一種自信的表現,fake it till you make it。你會留意很多於Liverpool street station或Canary Wharf或香港中環上班的金融人士都會展示出一種自信的姿態。
你會留意很多於Liverpool street station或Canary Wharf或香港中環上班的金融人士都會展示出一種自信的姿態。
  • Cover letter盡可能保持一頁內,不用太長令HR或經理不耐煩,這是因為一般的投行經理或HR都是比較看重CV去快速地理解你的經驗。
  • 如果你懂excel去整理數據的話,你申報投行的trading交易崗位(無論是實習還是畢業生的崗位)的時候就可以特別提及到你excel的能力,有VBA的經驗就更加可以寫進去。這是因為很多trading交易崗位都需要你用Excel去製作modelling或用Excel去整合數據,但不用怕,你申報工作的時候不需要先成為Excel modelling或VBA的高手。
  • 一般的線上檢測online competency reasoning test或online numerical test會先給你一些資訊或文章,然後會給你幾道選擇題multiple choice questions。為了節省時間,你可以先看那些題目,然後才看資訊或文章找出問題的答案。
  • 有一些線上檢測的問題實在是太難,但是你又要用20分鐘的短時間內答20道題,如果你覺得你不能用90秒內找出答案的話,我建議你還是把A,B,C,D隨機地選一個,始終有25%機會率可以答中,而你又可以省點時間作答下一道題。
  • 你可以嘗試網上搜索一下你報考公司的面試試題,有一些人會於網上分享自己面試的經歷 : )

最後祝大家新年快樂,學業進步,求職更上一層樓!

#求職 #投行 #Trading #面試 #簡歷

怎麼樣免付£12500入息的稅? 《英國暑假工/打工度假篇》

『在英國,每個人的年度基本免稅額是£12500,而過了£12500才要付20%。若你做了短期工作(如暑假工),英國稅務局(HMRC)通常會向你誤徵更多稅,所以你要知道怎麼樣退稅』

相信很多人都會記得收到人生第一份工資帶來的奇妙感受。

筆者幾年前於英國曼切斯特的MarkIt公司做暑假實習的工資是每週£350,但不知為什麼我於銀行實際上收到的是不多於£300; 我就立即懷疑我的工資有沒有被發錯了,但後來才發現原來英國徵收入息稅的方法跟香港的很不同 – 在英國,你被發的工資是稅後的工資,但在香港你被發的工資是稅前的工資。

英國的稅務年度是從每年的4月6日到下年的4月5日計起,而大學生通常都是於6月至9月花大約10個星期做“暑假工”,而大部分公司於10個星期內派發的全部工資應該不會超過£12500,再加上一般留學生於年度的其他日子也沒有任何收入,所以於下一年的4月5日後通知英國稅務局(HMRC)便可要求退還全部的入息稅。

退入息稅的步驟如下:

  1. 根據https://www.gov.uk/government/organisations/hm-revenue-customs/contact/income-tax-enquiries-for-individuals-pensioners-and-employees 所顯示的資料, 你要於週一到週五上午8時到下午8時或週六上午8時到下午4點撥打+44 135 535 9022 (請上網留意最新的服務電話/時間)
  2. 接通了便是機器的接線生問你問題,你要答”overpaid tax”
  3. 再答多幾道簡單問題後,你就就會跟真正的接線生跟你對話,你就跟他說你的National Insurance (NI) number和你暑假工的入息,他就會幫你計算你可以退還多少的入息稅。
  4. 他之後會詢問你要否把退還的款項透過郵寄一封支票給你,還是要把款項銀行匯款給你 – 我個人傾向都是銀行匯款(因為比較快和安全).若你選擇銀行匯款的話,他之後會要求你於英國稅務局(HMRC)的網站創建賬號,那你就直接用你的National Insurance (NI) number創建一個賬號。
  5. 創建之後,網站就會要求你填寫你的銀行戶口號碼(Account number)和sort code,填完並Submit之後等幾個工作天你就會收到退稅的款項