頭脳一式

人の記憶なんて曖昧なもの。すべての情報を頭に記憶するなんてナンセンス。困ったらここに来ればいいじゃん?

【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の入れ子構造)

作り方

1.Listクラスを作る。

クラス名はdataBeanで
メンバ変数str,num.flgとそれぞれのセッター/ゲッターと値確認用のOverrideしたtoString()を用意。

public class dataBean {
    private String     str;
    private int       num;
    private boolean   flg;

    public String getStr() {
        return str;
    }
    public void setStr(String str) {
        this.str = str;
    }

    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }

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

    @Override
    public String toString(){
        return str + "," + num + "," + flg;
    }
}

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

クラス名はMasterDataBeanでメンバ変数datainfoとセッター/ゲッターを用意。

public class MasterDataBean {
    public List<dataBean> datainfo;

    public List<dataBean> getDatainfo() {
        return datainfo;
    }

    public void setDatainfo(List<dataBean> list) {
        this.datainfo = list;
    }
}

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

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

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

    data.setStr("AMZN");
    data.setNum(11111);
    data.setFlg(true);
    list.add(data);

    data = new dataBean();
    data.setStr("FB");
    data.setNum(22222);
    data.setFlg(true);
    list.add(data);

    data = new dataBean();
    data.setStr("MSFT");
    data.setNum(33333);
    data.setFlg(true);
    list.add(data);

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

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

    data.setStr("AAPL");
    data.setNum(44444);
    data.setFlg(true);
    list.add(data);

    data = new dataBean();
    data.setStr("BABA");
    data.setNum(55555);
    data.setFlg(true);
    list.add(data);

    data = new dataBean();
    data.setStr("GOOG");
    data.setNum(66666);
    data.setFlg(true);
    list.add(data);
    
    //2件目のListを格納
    Mdata.setDatainfo(list);
    MstList.add(Mdata);

    
    System.out.println(MstList.get(0).getDatainfo());//1件目のListを出力
    System.out.println(MstList.get(1).getDatainfo());//2件目のListを出力

}

【出力結果】
[AMZN,11111,true, FB,22222,true, MSFT,33333,true]
[AAPL,44444,true, BABA,55555,true, GOOG,66666,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

【Javascript】クロージャとオブジェクト指向プログラミング

クロージャとは

オブジェクトの状態を保持する仕組みのこと。
つまり、オブジェクト指向プログラミングを可能にする。
下記を満たすとそのコードはクロージャとして機能する。

  • 関数の中にローカル変数と、もう一つ関数を用意する。
  • ネストした関数内でローカル変数を参照させる。
function closure(){
  var num=0;
  
  return function(){
    alert(num);
    num = num + 1;
  }
}

var c = new closure();
var d = new closure();
c();  //0
c();  //1
c();  //2
d();  //0
d();  //1
d();  //2

【Java】ジェネリクス(総称型)と型推論

ジェネリクス(総称型)とは

ジェネリクスとは、型を指定することによってコレクションが扱える型を限定的にする機能。
例えば、ArrayListを下記のように記述した場合、これはArrayListがString型しか扱えないことを指す。

ArrayList<String> array = new ArrayList<String>();

指定する型のことを型パラメータといい、ダイヤモンド演算子『<>』を用いて記述する。
なお、下記のように型変数を指定しない場合はObject型が渡されたものと推論される。

ArrayList array = new ArrayList();

ジェネリクスのメリット①:意図しない型による実行時エラーを防ぐ

例えば以下のようなコード。このArrayListは型を指定していないため、どんな型の値でも扱うことができる。

ArrayList array = new ArrayList<>();
array.add("abc");    //String
array.add(123);    //Integer
array.add(true);    //boolean

ジェネリクスを使わない場合、String型が来るとわかっていてもキャストしなければならず、またString型以外の値が来たときは実行時エラーになってしまう。

ArrayList array = new ArrayList();
array.add("abc");
array.add(123);
array.add(true);

String str1 = array.get(0);//この書き方ではコンパイルエラー。
String str2 = (String) array.get(0);//上のコードは←のようにキャストする必要がある。
String str3 = (String) array.get(1);//実行するとClassCastExceptionが発生する。 

下記のようにジェネリクスを利用することにより、コーディング段階で誤りに気付ける。

ArrayList<String> array = new ArrayList<String>();
array.add("abc");
array.add(123);    //ここでコンパイルエラーが発生。
array.add(true);    //ここでコンパイルエラーが発生。

ジェネリクスのメリット②:クラスの型を汎用的にできる

public class Generics<T> {
    private T element;

    public void setter(T element) {
        this.element = element;
    }

    public T getter() {
        return element;
    }
}

上記の<T>の部分にStringやIntegerを入れてインスタンス化することにより、String型のGenericsクラスやInteger型のGenericsクラスを作ることが出来る。

Generics<String> a = new Generics<String>();
a.setter("abc");
System.out.println(a.getter()); //abcが返却される。

Generics<Integer> b = new Generics<Integer>();
b.setter(123);
System.out.println(b.getter());    //123が返却される。

用語おさらい

用語 説明
<> ダイヤモンド演算子
<T> 型変数
型パラメータ Tの部分に代入するStringやIntegerのこと。

型推論とは

型推論とは、インスタンス生成時に、変数の型を決定する際、変数の宣言時と同じ型を使う機能のこと。
これにより今まで宣言時とインスタンス生成時の2箇所で型を記述していたのが1回で済むようになる。

ArrayList<String> array = new ArrayList<String>();  //従来の書き方
ArrayList<String> array2 = new ArrayList<>();   //これが型推論

【GoFデザインパターン】Strategyパターン

Strategyパターン

一言でいうとクラスをプラグイン化する。
共通の抽象クラス(又はインターフェース)を持つ複数のクラスを準備しておき、どれをnewするかを状況に応じて切り替える設計のことをStrategyパターンという。

JavaでStrategyパターン

以下はJavaで実装した例。

GameMode Gm = null;
String mode = "easy";

switch (mode) {
case "easy":
    Gm = new EasyMode();
    break;

case "normal":
    Gm = new NormalMode();
    break;

case "hard":
    Gm = new HardMode();
    break;
default :
    Class<?> Class = Class.forName(mode);
    Gm = (GameMode) Class.newInstance();
}

【Javascript】jsにおける関数と引数の扱い

関数

Javascriptの関数は第一級オブジェクト(ファーストクラスオブジェクト)と云い
変数や配列に代入することが出来る。パラメータとして使うことも可能。

関数の定義、実行

// 関数の定義
function add(a,b){
    console.log(a + b);  // 15
}

// 関数の実行
add(10,5);

変数へ代入、呼び出し実行する方法

変数へ代入するときは、関数名を付けない。(無名関数)

// 変数へ代入する方法  
var subtract = function (a,b){
    console.log(a - b);  // 5
}

// 呼び出し実行
subtract(10,5);

パラメータとして使う方法

function add(a,b){
    console.log("add");
}

var add = function (a,b) {
    console.log(a + b);  // 15
}

function func(add) {
    add(); //add関数を呼び出しているわけではなく、引数に渡された関数を実行している。
}

func(add(5,10));  //func関数の引数としてadd関数を渡す。

変数へ代入した関数の定義情報を表示する方法

var add = function (a,b) {
    alert(a + b);
}

console.log(add); //カッコ演算子を付けずに呼び出すと関数の中身を見ることが出来る。

引数

Javaなどでは関数の定義どおりに引数を渡さないとエラーになるが、
Javascriptではエラーにならない。引数を多く渡しても少なく渡しても問題なく実行することができる。

引数を多く渡した場合の挙動

function view(a,b,c){
    console.log(a, b ,c); // 10 20 30
}

view(10,20,30,40,50);

引数を少なく渡した場合の挙動

function view(a,b,c){
    console.log(a, b ,c);  // 10 20 undefined
}

view(10,20);

引数を渡さなかった場合の挙動

function view(a,b,c){
    console.log(a, b ,c); // undefined undefined undefined
}

view();

上の実行結果をみると値が渡されなかった引数を参照すると「undefined」が返却されることがわかる。
そして多く渡した引数はargumentsオブジェクトを用いることで値を参照することができる。
argumentsオブジェクトは、関数のスコープ内で使用することができ、関数に渡されたすべての引数を管理している。

function view(a,b,c){
    console.log(arguments.length); // 5
    console.log(arguments[0], arguments[1], arguments[2]); // 10 20 30
}

view(10,20,30,40,50);

コールバッグとは

引数として渡される関数のことをコールバック関数と呼ぶ。
引数として渡すことで任意のタイミングで処理を実行することが可能になる。
非同期処理の場合に、処理が終わってから関数を実行したい場合に有効。

function func1(callback){
    console.log("test1");
    callback();  //このコードが実行されたとき、引数に渡された関数が実行されることになる。
}


func1( function() {
    console.log("test2");  //test1 test2の順で出力される。
});

変数の巻き上げ

Javascriptでは関数内のいかなる場所でもvarを用いることで変数の宣言ができる。
但し、この変数はどこで宣言されたとしても関数の先頭で宣言されたときと同様の振る舞いをする。

var str = "abc";

var func = function(){
    console.log(str);  //undefined
    
    var str = "def";
    console.log(str);  //def
}

func();

上のコードは下記と同義。
宣言部分のみが先頭で行われたと見做される。(初期化まではされていないことに注意)

var str = "abc";

var func = function(){
    var str;
    console.log(str);  //undefined
    
    str = "def";
    console.log(str);  //def
}

func();

巻き上げされたままグローバル変数を呼び出したいときは「this.変数名」の形にする。

var str = "abc";

var func = function(){
    console.log(this.str);  //abc
    
    var str = "def";
    console.log(str);       //def
}

func();

関数内で使用するすべてのローカル変数を関数の先頭で宣言することにより巻き上げを防げる。

即時関数

関数を定義すると同時に実行することができる関数のことを即時関数と呼ぶ。
この即時関数は主に一回だけ必要な処理がある場合に使用する。
無名関数で即時関数を作ることでグローバルスコープの汚染(不要なメンバの追加)を回避することができる。
下のコードのように無名関数全体を()で括ることで定義・実行することができる。

//引数なしver
(function(){
    console.log("即時関数1");    // 即時関数1
}());

//引数ありver
(function(a,b){
    console.log(a + b);     // 即時関数2
}("即時","関数2"));