ハックライフノート

技術的な話とか、覚え書き

[Java]Mapインターフェースでよく使うHashMap、LinkedHashMap、TreeMapの違い

今回はJavaのMapインターフェースのお話です。

そもそもMapとは、任意の型同士をキーと値のセットで使用する使い所によっては便利なインターフェースです。

使い方としては、

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

な感じで、大抵の場合Mapインターフェースを実装したHashapクラスでインスタンス化する場合が大抵だと思います。

この場合、Stringクラスのキーと同じくStringクラスの値のセットで使用します。

が、ここでHashMapの特性を理解していないと、意外な所でつまづきます。

例えば、Mapの要素内を全て取り出したい時は拡張for文等で実装すると思いますが。

for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + ":" + entry.getValue());
}

といった感じで出力すると、出力される結果はランダムな要素順になってしまいます。

これはHashMapの特徴で、要素の追加順等は保有しません。

じゃあ要素の追加順で出力したい場合はどうするかと言うと、LinkedHashMapクラスでインスタンス化をします。

そうすると、先程の拡張for文で回してあげると、要素を追加した順に出力をしてくれます。

因みに、TreeMapというクラスもありますが、こちらの場合はキーを昇順に並べ出力してくれます。

まとめると・・・

1.HashMapは取り出す際、要素はランダム
2.LinkedHashMapは、追加(put)した順番
3.TreeMapは、キーを昇順に並べた順番

に出力されます。

[MySQL]CentOSへのMySQLインストール後mysql_secure_installationで躓いた話

新しくサーバ用のPCを買ったので、どうせならMySQLでもインストールしておこうと思いたったのが事の発端

環境はCentOS 7.5-1804のMySQL 5.7.22です。

MySQLは普通にyumするとMariaDBがインストールされるので、MySQLの公式からレポジトリを追加してyum install mysqlしてます。

さて、通常のやり方としては上記の通り本体をインストール後

sudo cat /var/log/mysqld.log | grep password

で初期パスワードをまず取得してから

mysql_secure_installation

をすると思いますが・・・ここで躓いた。

Access denied for user 'root'@'localhost'

rootパスワードを求められる所で、先程取得した文字列をちゃんと入れてもこの通り、ログインできません。

実はこの現象、RaspberryPiにMySQLを入れた際にも同様のエラーが起こったので、元々のバグなのか何なのか正直わかってません。

んで本題、これの解決法。

まずMySQLのサービスを停止します。

sudo systemctl stop mysqld.service

因みに、CentOS7からはsystemctlコマンドを使ってサービス(デーモン)の起動や停止を行います。

次に、/etc/my.cnfの[mysqld]の最後列にskip-grant-tablesを追記。

vi /etc/my.cnf
[mysqld]
skip-grant-tables

んで、MySQL起動。

sudo systemctl start mysqld.service

補足ですが、MySQLは停止しないままmy.cnfを編集後

sudo systemctl restart mysqld.service

でも行けると思います。

そしたら、MySQLに普通にログインします。

mysql -u root

パス無しで入れるので、後はmysqlスキーマのuserテーブルにあるauthentication_stringカラムがrootのpasswordを更新してあげてください。

UPDATE mysql.user
SET authentication_string=password('新しいrootパスをここに入れる')
WHERE user='root';

んで、MySQLをログアウト後、再度停止後my.cnfの追加した行を削除しmysqlを起動するか、編集後に再起動してください。

mysql -u root -p

で先程UPDATEしたパスワードを入力すれば、きっとログインができる喜びを味わえるでしょう。

もう既に2回も遭遇し2回対処しているので、手順を覚えそうです。覚えたくないけど。

[Windows10]ドライブがエクスプローラーで2重に表示される

タイトル通りですが、Windows10のエクスプローラーの左ツリーでドライブが2重に表示される問題があります。

f:id:miyatakaTK:20180519170349p:plain

上のスクリーンショットにあるように、赤枠で囲んだ部分が余計に表示されています。

これ、何故こうなっているかと言うと、赤枠の方はどうもリムーバブルディスクとして認識しているせいです。

USBメモリとか、そういった仲間に分類されてるんですね。

なんでやねん。

見た目上あまりよろしいものではないので、赤枠の方の表示を消します。


1.レジストリエディタを起動する
Win + Rキー同時押しで「ファイル名を指定して実行」を開き、名前に「regedit」と入力してEnterします。

このショートカットキーは便利なので覚えておいて損はないです。


2.レジストリの編集
レジストリの編集は自己責任で、万が一に備えてバックアップを取ったほうが吉です。

レジストリエディタが開いたら、

コンピューター\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\DelegateFolders

に移動します。

そこに {F5FB2C77-0E2F-4A16-A381-3E560C68BC83} という名前のキーがあるので、削除します。

3.あら不思議
f:id:miyatakaTK:20180519171528p:plain

エクスプローラーを再起動しなくても、こんな感じで2重表示が解消されていると思います。

と言うか、リムーバブルディスクとして認識しちゃダメでしょ、ってツッコみたいですね。

[MySQL]レコードが無ければINSERT、あればUPDATE

誰だって一度は夢見るINSERT文とUPDATE文の両立・・・

まあ、方法は色々とあるんですが、今回はON DUPULICATE KEY UPDATEを使ってスマートに実現しましょう。

こんな感じのクエリを書きます。

INSERT INTO table (column1, column2, column3)
VALUES (1, 2, 3)
ON DUPULICATE KEY UPDATE
column2 = 20, column3 = 30;

普通のINSERT文の後ろにON DUPULICATE KEY UPDATEを付けて、アップデート対象カラムと値を書くだけ。

ね、簡単でしょ?

ただし、レコードの有無の判定をする為、いずれかのカラムがプライマリキー(主キー)である必要があります。

上記の場合、例えばcolumn1がPKだとして1という値が無ければ
column1=1
column2=2
column3=3
なレコードがINSERTされます。

逆に、column1に既に1という値が存在すれば、そのレコードは
column2=20
column3=30
といった感じにUPDATEされます。

1クエリで同時にINSERTとUPDATEができるので、便利ですよ。

[VB.NET]DataViewのコピーでやられた話

初めての記事がこんなニッチな内容だけど、とりあえず書き残しておく。

仕事上でVB.NETを使った業務アプリケーションの開発を行っていて、DataViewを初めて扱った時につまづきました。

 例えば、こんなソースコードを書いたとする。

Dim dv1 AS New DataView
(dv1に適当なデータを入れた後)
Dim dv2 AS DataView = dv1

これでまーdv1の内容をdv2へとコピーできたかな、と思ったら大間違い。

この状態でdv2を編集すると、dv1にも影響します。

いわゆる値渡しじゃなくて参照渡し的な動作をしてくれやがります。(どうなってるかは分からない)

なんで、もしDataViewをコピーしたい時は

dv2.Table = dv1.Table.Copy()

てな感じで、TableプロパティのCopy()メソッドを使ってやればOK。


余談
Dataうんちゃら関係って多いですよね、DataSetとかDataTableとかDataRowとか・・・

これらは仮想的なデータベースを構築してやるクラス群なんですよね。

動作は遅いらしいですけどね。