頭脳一式

人の記憶なんて曖昧なもの。すべての情報を頭に記憶するなんてナンセンス。困ったらここに来ればいいじゃん?というスタンスで最強のナレッジベースを目指すブログ

【VSCode】便利なショートカットキーと拡張機能

VSCode独自のショートカットキーと拡張機能についてのまとめ。
Ctrl+fで検索みたいなどのアプリでも共通で有名なショートカットは省きます。

基本操作

コマンド 説明
Ctrl + h 置換。
Ctrl + , 設定画面を開く。
Ctrl + Shift + Enter 空行を追加する。
Atrl + Shift + ↑ カーソル行の内容を上の行にコピーする。
Atrl + Shift + ↓ カーソル行の内容を下の行にコピーする。
Ctrl + Shift + k カーソル行を削除する。
Ctrl + Shift + d デバッグを開く。
Ctrl + Shift + p コマンドパレットを開く。
Ctrl + Shift + x 拡張機能を開く。

拡張機能

Markdown All in One

VSCodemarkdown書きたいならコレ。
marketplace.visualstudio.com

ショートカット 説明
Ctrl + Shift + v プレビューを表示する。
コマンド 説明
Markdown:Print current document to HTML HTMLを生成する。

Markdown TOC

markdownで書いた文書の目次を生成するならコレ。 marketplace.visualstudio.com

https://raw.githubusercontent.com/AlanWalk/Markdown-TOC/master/img/insert-toc.gif

コマンド 説明
Markdown TOC:Insert/Update 目次を生成(更新)する。
Markdown TOC:Delete 目次を削除する。

VirtualBoxにインストールしたCentOS7にTeraTermからssh接続する

環境

  • ホストOS:Windows7 pro
  • ゲストOS:CentOS7
  • 仮想化ソフト:VirtualBox Ver5.2.4
  • SSHクライアント:Tera Term Ver4.96

方法1.NAT+ ポートフォワーディングで接続する

まずは、簡単なNAT+ ポートフォワーディングで接続するための手順です。

【前提】

  • CentOS7のインストール済みであること。
  • TeraTermがインストール済みであること。

手順1:VirtualBox側のネットワーク設定を行う。

  • VirtualBoxマネージャー > 設定 > ネットワークの順に選択し、割り当てをNATにする。
  • ▶高度を展開し、ポートフォワーディングを押下する。
    f:id:shiakisudev:20180813020026p:plain
手順1.1:ポートフォワーディングルールを設定する。
  • ホストポート:1234(任意)
  • ゲストポート:22(固定) f:id:shiakisudev:20180813020049p:plain

手順2:Tera Termを起動する。

  • ホスト:localhost
  • TCPポート:1234(手順1.1で設定したホストポートを指定する。) f:id:shiakisudev:20180813020314p:plain

ログイン完了!

f:id:shiakisudev:20180813021228p:plain f:id:shiakisudev:20180813020403p:plain

【Eclipse】デバッグ中に意図したタイミングでExceptionを発生させる方法

1.任意のソースをデバッグモードで実行する

任意のソースをデバッグモードで実行します。
このとき、「ウインドウ > ビューの表示 > 表示」で表示タブを表示し、発生させたいExceptionのコードを書きます。
例)throw new NullPointerException();
"Eclipceで任意のソースをデバッグモードで実行しているキャプチャ"

2.表示タブのコードを実行する。

表示タブに書いたコードを選択し、「右クリック >実行」で実行します。 表示タブのソースコードを実行しようとしているキャプチャ

すると、catch句の中に置いたBreakpointの位置で処理が止まります。 Catch句で処理が止まった状態のキャプチャ

これを使えばcatch句へ飛ばすためのテストコードをわざわざ書く必要が無くなりますね。

【アルゴリズム】LRU(Least Recently Used)の実装

LRUとは

www.weblio.jp

要するに、一番使われていないものを捨てて、新しいものと入れ替える方式のこと。

JavaでLRU(Least Recently Used)を実装してみる

今回は、最大で保持できる要素数は5個までとし、6個目の要素を格納したときに、
一番使われていない要素を捨てて6個目の要素を入れるような処理を目指します。

1.要素を5個まで保持できるLinkedHashMapの生成方法

まず、「最大で保持できる要素が5個まで」という仕組みを作ります。
具体的にはLinkedHashMapのremoveEldestEntryメソッドをオーバーライドし、
「return size() > 5;」とします。

public static void main(String[] args) {
    //↓↓インナークラスここから↓↓
    class LRU5 extends LinkedHashMap<String, String> {
        protected boolean removeEldestEntry(Map.Entry eldest) {
            return size() > 5;
        }
    }
    //↑↑インナークラスここまで↑↑

    tryLRU(new LRU5());
}

private static void tryLRU(Map map) {
    map.put("Amazon", "11111");
    map.put("Apple", "22222");
    map.put("MicroSoft", "33333");
    map.put("TOYOTA", "44444");
    map.put("NISSAN", "55555");
    System.out.println("5個目:" + map);

    map.put("Tesla", "66666");
    System.out.println("6個目追加:" + map);
}

実行すると以下の2行が出力されます。
5個目:{Amazon=11111, Apple=22222, MicroSoft=33333, TOYOTA=44444, NISSAN=55555}
6個目追加:{Apple=22222, MicroSoft=33333, TOYOTA=44444, NISSAN=55555, Tesla=66666}

removeEldestEntryはTrueを返すたびに、Mapの先頭の要素を削除します。
前後の出力結果を見比べると6個目のTeslaを追加された代わりに1個目のAmazonが無くなっていることが分かります。
これで「最大で保持できる要素が5個まで」という仕組みは完成です。

2.LinkedHashMapをアクセス順で要素を保持するMapにする方法

次に、「一番使われていない要素」を判定するためにMapをアクセス順に保持する必要があります。
インナークラスのインスタンスを生成する際の引数を以下のようにします。

new LRU5(5, 0.75f, true));

3.完成版ソース

前述の1と2を組み合わせて以下のようなソースにするとLRUとして機能します。

public static void main(String[] args) {

    //↓↓インナークラスここから↓↓
    class LRU5 extends LinkedHashMap<String, String> {
        LRU5(int i, float f, boolean b){
            super(i, f, b);
        }
        protected boolean removeEldestEntry(Map.Entry eldest) {
            return size() > 5;
        }
    }
    //↑↑インナークラスここまで↑↑

    tryLRU(new LRU5(5, 0.75f, true));
}

private static void tryLRU(Map map) {
    map.put("Amazon", "11111");
    map.put("Apple", "22222");
    map.put("MicroSoft", "33333");
    map.put("TOYOTA", "44444");
    map.put("NISSAN", "55555");
    System.out.println("アクセス前:" + map);
    map.get("Amazon");
    map.put("Tesla", "66666");
    System.out.println("アクセス後:" + map);
}

4.実行結果の解説

実行すると以下の2行が出力されます。
アクセス前:{Amazon=11111, Apple=22222, MicroSoft=33333, TOYOTA=44444, NISSAN=55555}
アクセス後:{MicroSoft=33333, TOYOTA=44444, NISSAN=55555, Amazon=11111, Tesla=66666}

put処理は要素アクセスしたと見做されるのでputした順に要素アクセスしたことになります。
5個putした時点では、一番最後にputした要素がNISSANなので一番最後にアクセスした要素もNISSANとなります。
ですが、 次の行でAmazonをgetしています。get処理もput処理と同様に要素にアクセスしたと見做されるため、この処理により一番最後にアクセスした要素がAmazonに変わります。
このタイミングでTeslaをputすると、アクセス順が若い要素(最も使われていない要素)はAppleとなるので、Appleが消え、代わりにTeslaが格納される結果となります。

【Java】Mapの種類と使い方(HashMap/TreeMap/LinkedHashMap)

Mapの種類

MAPの種類 説明
HashMap Keyからハッシュ値を算出して値を管理するMap。順序は保証されない。
TreeMapやLinkedHashMapよりも高速に動作する。
TreeMap Keyの昇順にソートされるMap。
LinkedHashMap デフォルトでは格納された順番を保持するMap。
コンストラクタの第3引数にtrueを設定するとアクセス順で要素を保持できる。

Mapの生成

//HashMapの生成
HashMap<String, Integer> hMap = new HashMap<String, Integer>();

//TreeMapの生成
TreeMap<String, Integer> tMap = new TreeMap<String, Integer>();

//LinkedHashMapの生成
LinkedHashMap<String, Integer> lMap = new LinkedHashMap<String, Integer>();

//型推論により、右辺のデータ型を省略することが可能。
Map<Integer, String> map2 = new HashMap<>();

主要なメソッド

メソッド 使い方
Map.put(key, value); マップを追加する。
Map.get(key) マップを取得する。
Map.remove(key) マップを削除する。
Map.clear() マップの要素を全て削除する。
Map.containsKey(key) 指定したKeyが存在する場合はTrue、存在しない場合はfalseを返す。
Map.size() マップの長さを取得する。
Map.entrySet() KeyとValueをセットで取得する。
Map.keySet() Keyのみを取得する。
Map.values() Valueのみを取得する。

Map.put(key, value)の使い方

第1引数にKey、第2引数にValueを指定する。

Map<String, String> map = new HashMap<>();

map.put("1", "Apple");
map.put("2", "Amazon");
map.put("3", "MicroSoft");

Map.get(key)の使い方

Keyを指定すると、Keyに対応するValueを返却する。

Map<String, String> map = new HashMap<>();
map.put("1", "Apple");
map.put("2", "Amazon");
map.put("3", "MicroSoft");

System.out.println(map.get("3"));//MicroSoft

keyが重複している場合は最後に格納された方が適用される。

Map<String, String> map = new HashMap<>();
map.put("1", "Apple");
map.put("2", "Amazon");
map.put("3", "MicroSoft");
map.put("3", "IBM");

System.out.println(map.get("3"));//IBM

Map.remove(key)の使い方

指定したKeyとValueを削除する。

Map<String, String> map = new HashMap<>();
map.put("1", "Apple");
map.put("2", "Amazon");
map.put("3", "MicroSoft");

map.remove("3");
System.out.println(map.get("3"));//null

Map.claer()の使い方

Map<String, String> map = new HashMap<>();
map.put("1", "Apple");
map.put("2", "Amazon");
map.put("3", "MicroSoft");

map.clear();
System.out.println(map);//{}
System.out.println(map.size());//0

Map.containsKey(key)の使い方

指定したKeyが存在すればTrueを返却し、存在しなければFalseを返却する。

Map<String, String> map = new HashMap<>();
map.put("1", "Apple");
map.put("2", "Amazon");
map.put("3", "MicroSoft");

System.out.println(map.containsKey("3"));//true
System.out.println(map.containsKey("4"));//false

Map.size()の使い方

Map<String, String> map = new HashMap<>();
map.put("1", "Apple");
map.put("2", "Amazon");
map.put("3", "MicroSoft");

System.out.println(map.size());//3

keyが重複している分はカウントされない。

Map<String, String> map = new HashMap<>();
map.put("1", "Apple");
map.put("2", "Amazon");
map.put("3", "MicroSoft");
map.put("3", "IBM");

System.out.println(map.size());//3

Mapのループ処理(Map.entrySet()の使い方)

MapのKey項目とValue項目を繰り返し取得する処理。

Map<String, String> map = new HashMap<>();
map.put("1", "Apple");
map.put("2", "Amazon");
map.put("3", "MicroSoft");

for(Map.Entry<String, String> map2 : map.entrySet()) {
    System.out.println(map2.getKey() + " : " + map2.getValue());
}
//【出力結果】
//1 : Apple
//2 : Amazon
//3 : MicroSoft

Mapのループ処理(Map.keySet()の使い方)

MapのKey項目を繰り返し取得する処理。

Map<String, String> map = new HashMap<>();
map.put("1", "Apple");
map.put("2", "Amazon");
map.put("3", "MicroSoft");

for(String map2 : map.keySet()) {
    System.out.println(map2);
}
//【出力結果】
//1
//2
//3

Mapのループ処理(Map.Values()の使い方)

MapのValue項目を繰り返し取得する処理。

Map<String, String> map = new HashMap<>();
map.put("1", "Apple");
map.put("2", "Amazon");
map.put("3", "MicroSoft");

for(String map2 : map.values()) {
    System.out.println(map2);
}
//【出力結果】
//Apple
//Amazon
//MicroSoft

【Java】Listの中にListを入れる(Listの入れ子構造)

完成図

先に、これから作るロジックの完成図のイメージ図を載せます。
f:id:shiakisudev:20180728231512p:plain

【解説】
クラス「MasterDataList」は複数のデータクラスを管理するためのクラスです。
クラス「vegetableData」は、野菜の情報を格納するためのクラスです。
クラス「fruitsData」は、果物の情報を格納するためのクラスです。

作り方

1.子データクラスを作る。

図中のvegetableDataクラスとfruitsDataクラスを作ります。
中身としてメンバ変数name,value.flgとそれぞれのセッター/ゲッターと値確認用のOverrideしたtoString()を用意します。
以下はvegetableDataクラスの例です。

public class vegetableData{
    private String    name;
    private int        value;
    private boolean    flg;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }

    public boolean isFlg() {
        return flg;
    }
    public void setFlg(boolean flg) {
        this.flg = flg;
    }

    @Override
    public String toString(){
        return name + "," + value + "," + flg;

    }
}

2.子データクラス格納用の親データクラスを作る。

図中のvegetableDataとfruitsDataのList型を格納するためのクラス「MasterDataList」を作ります。
中身としてメンバ変数vegeInfoとfruitsInfoをList型で定義し、セッター/ゲッターを用意します。

public class MasterDataList{
    public List<vegetableData> vegeInfo;
    public List<fruitsData> fruitsInfo;

    public List<vegetableData> getVegeInfo() {
        return vegeInfo;
    }

    public void setVegeInfo(List<vegetableData> list) {
        this.vegeInfo = list;
    }

    public List<fruitsData> getFruitsInfo() {
        return fruitsInfo;
    }

    public void setFruitsInfo(List<fruitsData> fruitsInfo) {
        this.fruitsInfo = fruitsInfo;
    }
}

3.データの生成・格納・出力

public static void main(String[] args) {
    List<MasterDataList> MstList = new ArrayList<MasterDataList>();
    MasterDataList Mdata;

//以下vegetableDataの編集--------------------------------------
    List<vegetableData> list;
    vegetableData data;

    //1件目のListを生成
    Mdata = new MasterDataList();
    list = new ArrayList<vegetableData>();
    data = new vegetableData();

    data.setName("玉ねぎ");
    data.setValue(30);
    data.setFlg(true);
    list.add(data);

    data = new vegetableData();
    data.setName("人参");
    data.setValue(100);
    data.setFlg(true);
    list.add(data);

    data = new vegetableData();
    data.setName("じゃがいも");
    data.setValue(50);
    data.setFlg(true);
    list.add(data);

    //1件目のListを格納
    Mdata.setVegeInfo(list);
    MstList.add(Mdata);

    //2件目のListを生成
    Mdata = new MasterDataList();
    list = new ArrayList<vegetableData>();
    data = new vegetableData();

    data.setName("大根");
    data.setValue(100);
    data.setFlg(true);
    list.add(data);

    data = new vegetableData();
    data.setName("白菜");
    data.setValue(200);
    data.setFlg(true);
    list.add(data);

    data = new vegetableData();
    data.setName("きゅうり");
    data.setValue(30);
    data.setFlg(true);
    list.add(data);

    //2件目のListを格納
    Mdata.setVegeInfo(list);
    MstList.add(Mdata);

//以下fruitsDataの編集--------------------------------------
    List<fruitsData> list2;
    fruitsData data2;

    //3件目のListを生成
    Mdata = new MasterDataList();
    list2 = new ArrayList<fruitsData>();
    data2 = new fruitsData();

    data2.setName("バナナ");
    data2.setValue(100);
    data2.setFlg(true);
    list2.add(data2);

    data2 = new fruitsData();
    data2.setName("レモン");
    data2.setValue(150);
    data2.setFlg(true);
    list2.add(data2);

    data2 = new fruitsData();
    data2.setName("リンゴ");
    data2.setValue(200);
    data2.setFlg(true);
    list2.add(data2);

    //3件目のListを格納
    Mdata.setFruitsInfo(list2);
    MstList.add(Mdata);

//以下、出力結果--------------------------------------
    System.out.println(MstList.get(0).getVegeInfo());//1件目のListを出力
    System.out.println(MstList.get(1).getVegeInfo());//2件目のListを出力
    System.out.println(MstList.get(2).getFruitsInfo());//3件目のListを出力

}

【出力結果】
[玉ねぎ,30,true, 人参,100,true, じゃがいも,50,true]
[大根,100,true, 白菜,200,true, きゅうり,30,true]
[バナナ,100,true, レモン,150,true, リンゴ,200,true]

総評

なんかいろいろ応用できそうです。

【SQL】副問い合せ(サブクエリ)の書き方4選

副問い合せ(サブクエリ)とは

SQL文の中にSELECT文をネストする記法のこと。
内側のSELECT文(ネストしたSELECT文)の実行結果に基づいて、外側のSQL文を実行することができる。

次の2つのテーブルを使って副問い合せ(サブクエリ)の書き方をまとめてみる。

<表名:株(kabu)>

ティッカー
ticker
銘柄名
stockName
時価総額(千ドル)
cap
市場
market
セクター
sector
AAPL アップル 942231955 NASDAQ テクノロジー
AMZN アマゾン 817117254 NASDAQ 生活必需品
MSFT マイクロソフト 780843362 NASDAQ テクノロジー
BABA アリババ 526175666 NASDAQ 生活必需品
FB フェイスブック 453576433 NASDAQ コミュニケーション
GOOG グーグル 391130080 NASDAQ コミュニケーション
JPM JPモルガン 378304764 NYSE ファイナンシャル
XOM エクソンモービル 353948559 NYSE エネルギー

<表名:ポートフォリオ(portfolio)>

ティッカー
ticker
銘柄名
stockName
枚数
AMZN アマゾン 5
NFLX ネットフリックス 8
XOM エクソンモービル 10

※kabuテーブルは米国企業の時価総額の上位8社をまとめた表で
portfolioテーブルは保有している銘柄をまとめた表です。

副問い合せの結果が単一行の場合の書き方

副問合せの結果が単一行になる場合は=演算子を用いる。

例題1:「株テーブルの中で時価総額が最大となる銘柄名とその時価総額を取得する」
この例題の結果を取得するSQL文は以下のとおり。

SELECT stockName,cap
FROM kabu
WHERE cap = ( SELECT MAX(cap) FROM kabu )

解説

①.内側のSELECT文が実行され、表内の最大となる時価総額「942231955」を取得する。

時価総額(千ドル)
cap
942231955

②.3行目のWHERE cap = ( SELECT MAX(cap) FROM kabu )だった箇所が
WHERE cap = 942231955と等価になる。

③.SELECT stockName,cap FROM kabu WHERE cap = 942231955 が実行され例題の結果を取得することができる。
<実行結果>

銘柄名
stockName
時価総額(千ドル)
cap
アップル 942231955

副問い合せの結果が複数行になる場合の書き方

副問合せの結果が複数行になる場合は=ではなく、IN演算子,ANY演算子,ALL演算子を用いる。

例題2:「株テーブルから、ポートフォリオテーブルに存在する全tickerの時価総額を取得する。」
この例題の結果を取得するSQL文は以下のとおり。

SELECT ticker,stockName,cap
FROM kabu

WHERE ticker IN (SELECT ticker FROM portfolio)

解説

①.内側のSELECT文が実行され、portfolioテーブルのtickerを取得する。

ティッカー
ticker
AMZN
NFLX
XOM

②.3行目のWHERE ticker IN ( SELECT ticker FROM portfolio )だった箇所が
WHERE ticker IN ('AMZN','NFLX','XOM')と等価になる。

③.SELECT ticker,stockName,cap FROM kabu WHERE ticker IN ('AMZN','NFLX','XOM')
が実行され例題の結果を取得することができる。
<実行結果>

ティッカー
ticker
銘柄名
stockName
時価総額(千ドル)
cap
AMZN アマゾン 817117254
XOM エクソンモービル 353948559

※portfolioテーブル上に存在するNFLX(ネットフリックス)は、株テーブル上には存在しないため抽出されない。

副問い合せの結果が表形式の場合の書き方

INSERT文やUPDATE文などで真価を発揮する。

例題3:「例題2の結果を別テーブルへINSERTする。」
この例題を満たすSQL文は以下のとおり。

INSERT INTO kabu (ticker,stockName,cap)
SELECT ticker,stockName,cap
FROM kabu
WHERE ticker IN (SELECT ticker FROM portfolio)
解説

①.内側のSELECT文が実行され、例題2の結果を取得する。

ティッカー
ticker
銘柄名
stockName
時価総額(千ドル)
cap
AMZN アマゾン 817117254
XOM エクソンモービル 353948559

②.取得した結果をINSERTする。

相関副問い合せ(相関サブクエリ)の書き方

相関サブクエリとは、副問い合せの形になっていてかつ、内側から外側の表や列を参照する記法のこと。

通常のサブクエリが内側のSELECT文の結果に基づき外側のSQLを実行するのに対し、
相関サブクエリは外側の実行結果1件に対して内側のSELCT文が実行される

上記のことから相関サブクエリはループのような振る舞いをするため、パフォーマンスが悪くなる傾向にある。

例題4:「株テーブルに、セクター別の最高時価総額も併せて表示する。」
この例題の結果を取得するSQL文は以下のとおり。

SELECT ticker,
   stockName,
   cap,
    sector,    
   (SELECT MAX(cap)
   FROM kabu AS k2
   WHERE k1.sector = k2.sector) AS MAX_cap_sector
FROM kabu AS k1
ORDER BY cap DESC

解説

①.外側の1件に対して内側のSELCT文を実行する。
【ループ1回目】
株テーブルの1件目はアップルです。
アップルのセクターはテクノロジーのため、このときの内側のSELECT文は以下のように置き換わります。

SELECT MAX(cap)
    FROM kabu k2
    WHERE 'テクノロジー' = k2.sector

このSELECT文の結果は下記になるため、アップルに紐づくセクター別の最高時価総額は’942231955’になります。

MAX(CAP)
942231955

--
【ループ2回目】
株テーブルの2件目はアマゾンです。
アマゾンのセクターは生活必需品のため、このときの内側のSELECT文は以下のように置き換わります。

SELECT MAX(cap)
    FROM kabu k2
    WHERE '生活必需品' = k2.sector

このSELECT文の結果は下記になるため、アマゾンに紐づくセクター別の最高時価総額は’817117254’になります。

MAX(CAP)
817117254

【ループ3回目以降】
株テーブルの3件目のマイクロソフトの場合も、1件目のアップルや2件目のアマゾンの場合と同様に抽出していきます。
これを株テーブルの件数分繰り返すと以下の結果になります。
<実行結果>

ティッカー
ticker
銘柄名
stockName
時価総額(千ドル)
cap
市場
market
セクター
sector
セクター別最高時価総額
MAX_cap_sector
AAPL アップル 942231955 NASDAQ テクノロジー 942231955
AMZN アマゾン 817117254 NASDAQ 生活必需品 817117254
MSFT マイクロソフト 780843362 NASDAQ テクノロジー 942231955
BABA アリババ 526175666 NASDAQ 生活必需品 817117254
FB フェイスブック 453576433 NASDAQ コミュニケーション 453576433
GOOG グーグル 391130080 NASDAQ コミュニケーション 453576433
JPM JPモルガン 378304764 NYSE ファイナンシャル 378304764
XOM エクソンモービル 353948559 NYSE エネルギー 353948559