talosのプログラミング教室

Java Silver合格への道 ~コンスタントプール~

こんにちは。たろすです。

今回はコンスタントプールについて説明します。

a == b

Javaではa == bと書くとaとbが同一かを判定し、同一であればtrue、同一でなければfalseを返します。

つまり以下のようなプログラムを実行すると「false」と表示されます。

public class Main {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ

		Food a = new Food("gohan");
		Food b = new Food("cake");

		System.out.println(a == b);
	}

}

どこからどう見ても別のオブジェクトですからね。

それでは次のプログラムはどうでしょうか。

public class Main {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ

		Food a = new Food("gohan");
		Food b = new Food("gohan");

		System.out.println(a == b);
	}

}

実はこの場合も「false」と表示されます。

なぜなら別々にインスタンス化しているため、別のインスタンスとして扱われるからです。

コンスタントプール

String型の場合はダブルクォーテーションで括られた文字列を記述するだけでインスタンス化できます。

つまり、わざわざnewしなくてもインスタンス化できるため以下のように書くことができます。

public class Main {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		
		String a = "gohan";
		String b = "gohan";

		System.out.println(a == b);
	}

}

しかし、このプログラムを実行すると「true」と表示されます。

なぜこのような挙動をするかというとコンスタントプールという仕組みがあるからです。

コンスタントプールは文字列リテラルを定数値としてインスタンスとは異なるメモリに保存し、どの変数から参照されても同じ文字列の場合は同じ場所を参照することでメモリの消費を減らす仕組みです。

つまりこのプログラムでは変数aも変数bもコンスタントプール内の同じ場所を参照しているため、aとbは同一であると判定されたわけです。


一方で、newした場合は新しいインスタンスが作られるため、以下のプログラムを実行すると「false」と表示されます。

public class Main {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ

		String a = new String("gohan");
		String b = new String("gohan");

		System.out.println(a == b);
	}

}

つまりこの書き方はメモリを無駄に消費しているので、実際にはやらないほうが良いです。

おわりに

今回はコンスタントプールについて説明しました。

String型の比較はequals()を使うのが普通なので意外とこの仕組みは知らないかもしれませんね。


【Java】パスワードのハッシュ化とログイン認証

こんにちは。たろすです。

今回は安全なアプリを開発するために重要なパスワードのハッシュ化について説明します。

ハッシュ化のアルゴリズムとしては「bcrypt」を使用します。

環境

言語:Java8
フレームワーク:Spring Security
DB:MySQL

下準備

mvnrepository.com

このサイトからjarファイルをダウンロードします。

f:id:talosta:20201227173038p:plain

Eclipseの動的Webアプリケーションであれば、ダウンロードしたjarファイルをWEB-INF/libにコピーしましょう。

解説

認証関連はAutuUtilクラスに実装されています。

まずはSpring Securityを使うために以下をインポートします。

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

パスワードのハッシュ化

/**
 * ユーザーを登録する
 * @param user
 * @return
 */
public boolean registerUser(UserSample user) {
	BCryptPasswordEncoder bcpe = new BCryptPasswordEncoder();
	// ハッシュ化
	String encodeedPassword = bcpe.encode(user.getPassword());
	user.setPassword(encodeedPassword);

	int result = userLogic.insertUser(user);
	if (result > 0) {
		return true;
	}
	return false;
}

ハッシュ化するときにはBCryptPasswordEncoder.encode()メソッドを呼びます。

引数は生のパスワード(ハッシュ化する前のパスワード)です。

ログイン認証

/**
 * ログイン処理を行う
 * @param user
 * @return
 */
public boolean login(UserSample user) {
	// IDをキーにユーザー情報を取得
	UserSample compUser = userLogic.getUserById(user.getId());
	BCryptPasswordEncoder bcpe = new BCryptPasswordEncoder();
	// 入力されたパスワードとDBのパスワード(ハッシュ化済み)を比較
	if (bcpe.matches(user.getPassword(), compUser.getPassword())) {
		loginUser.setUser(compUser);
		return true;
	}
	return false;
}

ユーザーから入力されたパスワードとDBに登録されているハッシュ化されたパスワードが一致しているかを確認するにはBCryptPasswordEncoder.matches()を使います。

第一引数は生のパスワード(ユーザーから入力されたパスワード)、第二引数はハッシュ化されたパスワード(DBに登録されたパスワード)です。


スポンサーリンク



実行

実行するとトップページが開くので「新規登録」を押します。

f:id:talosta:20201228230344p:plain

ID、名前、パスワードをすべて入力して「登録」を押します。

f:id:talosta:20201228230422p:plain

DBに登録されました。

パスワードはちゃんとハッシュ化されています。

f:id:talosta:20201228230448p:plain

先程登録したIDとパスワードを入力して「ログイン」を押します。

f:id:talosta:20201228232128p:plain

登録した名前が表示されます。

f:id:talosta:20201228232146p:plain

おわりに

今回はパスワードのハッシュ化とログイン認証について説明しました。

不明点があればコメントお願いします。

【Python】Twitter APIで一方的にフォローしている人を洗い出して自動フォロー解除する

こんにちは。talosです。

TwitterなどのSNSで一方的にフォローしているのって悲しいですよね。

だからと言って一人ひとり解除するのは面倒くさい…

なのでTwitter APIを使って一方的にフォローしている人を洗い出し、フォロー解除します。

環境

言語:Python
ライブラリ:tweepy

事前準備

Twitter APIの申請をしてある必要があります。

申請の方法はGoogleで調べればいくらでも出てくるのでここでは触れません。

方針

1.フォローしている人とフォロワーをリストアップする

2.1で作成したリストを比較してフォローしている人のリストにだけ存在する人をリストアップする

3.2で作成したリストのユーザーをフォロー解除する

フォローしている人とフォロワーをリストアップする

CK、CS、AT、ASにはそれぞれご自身で取得したAPI KEY、API secret key、Access token、Access token secretを入れてください。

また、「フォロワー取得」と「フォローしている人取得」で呼んでいるtweepy.Cursor()のidのところにご自身のアカウント名(@からはじまるやつ)を入れてください。

CSV出力」をするフォルダはご自身の環境に合わせて決めてください。

import tweepy
import pandas as pd

CK = '****'    # API KEY
CS = '****'    # API secret key
AT = '****'    # Access token
AS = '****'    # Access token secret

auth = tweepy.OAuthHandler(CK, CS)
auth.set_access_token(AT, AS)
api = tweepy.API(auth, wait_on_rate_limit=True)

cols = ['id']
# フォロワー格納用DataFrame
followers_ids = pd.DataFrame([], columns=cols)
# フォローしている人格納用DataFrame
followings_ids = pd.DataFrame([], columns=cols)

# フォロワー取得
itr = tweepy.Cursor(api.followers_ids, id='****', cursor=-1).items()   
for follower_id in itr:
    record = pd.Series([follower_id], index=followers_ids.columns)
    followers_ids = followers_ids.append(record, ignore_index=True)

# フォローしている人取得
itr = tweepy.Cursor(api.friends_ids, id='****', cursor=-1).items()   
for following_id in itr:
    record = pd.Series([following_id], index=followings_ids.columns)
    followings_ids = followings_ids.append(record, ignore_index=True)

# CSV出力
followers_ids.to_csv('../csv/followers.csv')
followings_ids.to_csv('../csv/followings.csv')

これを実行するとフォロワーのIDをリスト化したCSVファイルとフォローしている人のIDをリスト化したCSVが作成されます。

フォロワーのリスト
f:id:talosta:20210114163212p:plain

フォローしている人のリスト
f:id:talosta:20210114163358p:plain

なおここでいうIDはアカウント名とは異なります。

現時点ではIDが誰のものかわかりませんが、後ほどわかるのでここでは置いておきます。


スポンサーリンク



一方的にフォローしている人をリストアップする

こちらもフォルダを三か所で指定しているので、ご自身の環境に合わせて修正してください。

import tweepy
import pandas as pd

CK = '****'    # API KEY
CS = '****'    # API secret key
AT = '****'    # Access token
AS = '****'    # Access token secret

auth = tweepy.OAuthHandler(CK, CS)
auth.set_access_token(AT, AS)
api = tweepy.API(auth, wait_on_rate_limit=True)

# フォロワーのリストを読み込む
followers_ids = pd.read_csv('../csv/followers.csv', index_col=0)
# フォローしている人のリストを読み込む
followings_ids = pd.read_csv('../csv/followings.csv', index_col=0)

# 一方的にフォローしている人格納用DataFrame
oneside_follow = pd.DataFrame([], columns=['id', 'name', 'screen_name', 'description'])

# フォローしている人リストに存在していてフォロワーリストに存在していないユーザーを抽出
for following_id in followings_ids['id']:
    if following_id not in followers_ids['id'].values:
        # ユーザーの情報を取得
        user = api.get_user(following_id)
        record = pd.Series([user.id, user.name, user.screen_name, user.description], index=oneside_follow.columns)
        oneside_follow = oneside_follow.append(record, ignore_index=True)

# CSV出力
oneside_follow.to_csv('../csv/oneside_follow.csv')

これを実行すると一方的にフォローしている人の情報をリスト化したCSVが作成されます。

f:id:talosta:20210114164911p:plain

IDだけでなくユーザー名やアカウント名、自己紹介文も出力するようにしたので、確認してフォロー解除したくない人は消しておきましょう。

一方的にフォローしている人をフォロー解除する

こちらもフォルダを二か所で指定しているので、ご自身の環境に合わせて修正してください。

import tweepy
import pandas as pd

CK = '****'    # API KEY
CS = '****'    # API secret key
AT = '****'    # Access token
AS = '****'    # Access token secret

auth = tweepy.OAuthHandler(CK, CS)
auth.set_access_token(AT, AS)
api = tweepy.API(auth, wait_on_rate_limit=True)

# 一方的にフォローしている人リストを読み込む
oneside_follow = pd.read_csv('../csv/oneside_follow.csv', index_col=0)

# フォロー解除済みユーザー格納用DataFrame
removed_users = pd.DataFrame([], columns=['id', 'name', 'screen_name', 'description'])

# フォロー解除
for remove_id in oneside_follow['id']:
    user = api.destroy_friendship(remove_id)
    record = pd.Series([user.id, user.name, user.screen_name, user.description], index=oneside_follow.columns)
    removed_users = removed_users.append(record, ignore_index=True)

# CSV出力
removed_users.to_csv('../csv/removed_users_'+ datetime.datetime.now().strftime('%y%m%d%H%M%S') + '.csv')

これを実行するとフォロー解除し、フォロー解除したユーザーのリストを作成します。

f:id:talosta:20210114171129p:plain

実際にフォローが外れているか確認してみてください。

おわりに

Twitter APIの申請は大変ですがぜひ試してみてください。

令和2年度応用情報技術者試験振り返り

こんにちは。talosです。

先日受験した令和2年度秋期応用情報技術者試験の結果が出たので振り返っていきます。

春期の試験に向けて勉強を開始

内定を受けた会社から応用情報技術者試験の受験と勉強を課されました。

会社が通信教育を受けさせてくれたのでやってましたが、すべて終わらせることはできませんでした。

春期の試験が中止に

新型コロナウイルス感染症が流行し、春期の試験が中止になりました。

そのときは受かる自信があったので非常に残念でした。
(今思うとあのときの実力では受からなかったと思います)

返金されたのは不幸中の幸いでした。

秋期の試験に向けて勉強を開始

今回はひたすら過去問を解きました。

春のときに通信教育から過去問が送られてきていたのでそれを解きました。

移動中には応用情報技術者試験ドットコムも利用しました。

www.ap-siken.com

試験当日

感染予防のため1人1机でした。

神経質の私としては非常によかったです。

周りに物音を立てる人や貧乏ゆすりする人もいなかったので最高のコンディションで挑めました。


午前問は過去問からかなりの数が出ていたので余裕でした。

やはりやるべきは過去問です。

しかし午後になり恐ろしいことが起こります。

得点源だった情報システム開発アジャイルについての問題で一問もわかりませんでした。

急遽念のため勉強しておいたデータベースを解きました。

ちなみに午後問は以下を解きました。

・情報セキュリティ
・プログラミング
・データベース
・プロジェクトマネジメント
・システム監査


スポンサーリンク



自己採点

数日後、解答速報を見て自己採点してみました。


予想得点
午前 87.5点
午後 65~73点

解答を発表している会社によって正解は違うため多少の幅はあるものの、60点以上はとれそうです。

余程のことがなければ大丈夫そうだと安心しました。

結果は…

クリスマス、合否が発表されました。

結果は合格です。

得点は以下のようでした。


得点
午前 88.75点
午後 70.00点


午前分野別得点 得点 満点 得点率
ストラテジ系 23.75点 25.00点 95.0%
マネジメント系 11.25点 12.50点 90.0%
テクノロジ系 53.75点 62.50点 86.0%

なぜが午前の点数が予想と違いますね。

問題によって配点が違うのでしょうか。

午後は概ね予想通りです。

おわりに

受かっていて一安心です。

あまり参考になるような情報は書いていないですが、応用情報を受けるモチベーションになればと思います。

次はJava Silverかなぁ。


初心者に贈るアルゴリズム論

こんにちは。talosです。

プログラミング初心者に是非読んでいただきたいアルゴリズムの記事のまとめです。

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

基本情報技術者試験・応用情報技術者試験対策まとめ

こんにちは。talosです。

基本情報技術者試験応用情報技術者試験の対策のまとめです。

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com

talosta.hatenablog.com


今後も追加していく予定です。

Java Silver合格への道 ~X進表記~

こんにちは。talosです。

今回はX進表記についてです。

種類

10進表記

特別な表記はしません。

int d = 100;

2進表記

先頭に0bを付けます。

0bより後ろに0と1以外の数値が使われていたらコンパイルエラーになります。

int b = 0b10;

8進表記

先頭に0を付けます。

0より後ろに8以上の数値が使われていたらコンパイルエラーになります。

int o = 012;

16進表記

先頭に0xを付けます。

0xより後ろにG以降のアルファベットが使われていたらコンパイルエラーになります。

int h = 0xABC;