Java Silver合格への道 ~アンダースコアを用いた数値表記~
Java Silver合格への道 ~可変長引数~
こんにちは。たろすです。
今回は可変長引数についてです。
可変長引数の使い方
public class Sample { public void method(int... values) { for (int value : values) { System.out.println(value); } System.out.println("------------"); } }
メソッドの引数に注目してください。
「int... values」と書かれています。
引数の型の直後に「...」を付けることで可変長引数にすることができます。
可変長引数として渡された引数は配列として扱われます。
このメソッドを実際に使ってみましょう。
public class Main { public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ Sample sample = new Sample(); sample.method(1, 2, 3); sample.method(1, 2, 3, 4, 5); } }
// 出力 1 2 3 ------------ 1 2 3 4 5 ------------
引数に好きなだけ値を渡すことができます。
制約
可変長引数以外の引数も受け取る場合は、可変長引数が最後の引数になるようにしなければなりません。
例えば以下のようなプログラムはコンパイルエラーになります。
public void method(int... values, String str) { }
以下のように直しましょう。
public void method(String str, int... values) { }
可変長引数を二つ以上受け取るのもNGです。
おわりに
今回は可変長引数について説明しました。
配列を渡せば済む話なので、あまり使われているところは見たことありません。
Java Silver合格への道 ~ラベル~
こんにちは。たろすです。
今回はラベルについてです。
ラベルの使い方
まず以下のコードを見てください。
public class Main { public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { System.out.println(i + " " + j); if (j == 3) { break; } } } } }
二重ループがあり、内側のループの中でjが3と等しければbreakするような構造になっています。
そのためこのプログラムを実行すると、
0 0 0 1 0 2 0 3 1 0 1 1 1 2 1 3 2 0 2 1 2 2 2 3 3 0 3 1 3 2 3 3 4 0 4 1 4 2 4 3
と出力されます。
j(右側の列)が3になったろころで内側のループを抜けていることがわかります。
次に以下のコードを見てください。
public class Main { public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ a: for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { System.out.println(i + " " + j); if (j == 3) { break a; } } } } }
先程と異なるのは外側のforの左側に「a:」がついていることと、breakの右側に「a」がついていることです。
これをラベルと呼びます。
このプログラムを実行すると以下の出力が得られます。
0 0 0 1 0 2 0 3
jが3と等しくなったところで外側のループを抜けていることがわかります。
これはラベルを付けたことでbreakと外側のforを紐づけたからです。
このようにラベルを使うことでbreakするループを変えたりすることができます。
Java Silver合格への道 ~配列の宣言と初期化~
こんにちは。たろすです。
今回は配列の宣言と初期化についてです。
宣言
OK例
// よく使われる宣言 int[] a; // 変数名の後に[]を書くことも可能 int b[]; // 多次元配列も同様 int[][] c; int d[][]; // 分けることもできる int[] e[];
NG例
// 宣言時に要素数は指定しない int a[3];
初期化
OK例
// 要素を指定するパターン int[] a = { 1, 2, 3 }; // やっていることは上と同じ int[] b = new int[] { 1, 2, 3 }; // 要素数だけを指定するパターン(要素は初期値) int[] c = new int[3]; // 多次元配列の場合は{}の数に注意 int[][] d = { { 1, 2 }, { 3, 4 } }; // 要素なしの場合は多次元配列でも{}は1つでOK int[][] e = {}; // N次元目までは要素数を決めておき、N+1次元目以降の要素数は未定にしておくことができる int[][][]f = new int[3][][];
NG例
// {}を使う場合は要素数を指定しない int[] a = new int[3] { 1, 2, 3 }; // 宣言と{}を使った初期化は分けられない int[] b; b = {1 ,2, 3}; // 次元数が一致しない int[][] c = { 1, 2, 3 }; // N次元目の要素数が決まっていないのに、N+1次元目以降の要素数を決めることはできない int[][][] d = new int [][3][];
おわりに
今回は配列の宣言と初期化についてOK例とNG例を挙げました。
他の言語などを触っていると間違えやすいので要注意です。
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」を使用します。
解説
認証関連は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に登録されたパスワード)です。
スポンサーリンク
実行
実行するとトップページが開くので「新規登録」を押します。
ID、名前、パスワードをすべて入力して「登録」を押します。
DBに登録されました。
パスワードはちゃんとハッシュ化されています。
先程登録したIDとパスワードを入力して「ログイン」を押します。
登録した名前が表示されます。
【Python】Twitter APIで一方的にフォローしている人を洗い出して自動フォロー解除する
こんにちは。talosです。
TwitterなどのSNSで一方的にフォローしているのって悲しいですよね。
だからと言って一人ひとり解除するのは面倒くさい…
なのでTwitter APIを使って一方的にフォローしている人を洗い出し、フォロー解除します。
環境
言語:Python
ライブラリ:tweepy
方針
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が作成されます。
フォロワーのリスト
フォローしている人のリスト
なおここでいう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が作成されます。
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')
これを実行するとフォロー解除し、フォロー解除したユーザーのリストを作成します。
実際にフォローが外れているか確認してみてください。