よく使用されるAPIと基本アルゴリズム
クラス名とその役割を覚え、他の詳細はAPIドキュメントを参照しましょう
Math
- 数学計算を行うためのユーティリティクラスです
- コンストラクタは非公開で、すべてのメソッドはstaticです
主なメソッド:
- abs(int a) パラメータの絶対値を取得
- ceil(double a) 切り上げ
- floor(double a) 切り捨て
- round(float a) 四捨五入
- max(int a, int b) 2つの値のうち大きい方を返す
- pow(double a, double b) aのb乗を返す
- random() 0.0から1.0までのdouble型の乱数を返す
- cbrt() 立方根を計算
- sqrt() 平方根を計算
System
- exit(int status) 現在実行中のJava仮想マシンを終了
- currentTimeMillis() 現在システム時間をミリ秒値で返す(プログラム実行時間の計測に使用)
- arraycopy(ソース配列, 開始インデックス, 宛先配列, 開始インデックス, コピー個数) 配列のコピー
int[] srcArray = {1,2,3,4,5,6,7,8,9,10};
int[] destArray = new int[10];
System.arraycopy(srcArray, 0, destArray, 4, 3);
//destArray: 0000123000
コピー時の注意点:
- ソース配列と宛先配列の両方が基本データ型の場合、型は一致させる必要があります。そうでないとエラーが発生します
- 配列の長さを考慮する必要があります。範囲を超えるとエラーが発生します
- 両方が参照データ型の場合、サブクラス型は親クラス型に代入できます
Runtime
現在の仮想マシンの実行環境を表します 非staticクラスなので、オブジェクトを作成してメソッドを呼び出します
ObjectとObjects
ObjectはJavaの最上位親クラスです。すべてのクラスは直接または間接的にObjectクラスを継承しています。 Objectクラスのメソッドはすべてのサブクラスでアクセスできるため、Objectクラスとそのメソッドを理解する必要があります コンストラクタは引数なしのものだけです
3つの主要なメソッド:
toStringメソッド:
オブジェクトを印刷してプロパティ値を見たい場合、toStringメソッドをオーバーライドします オーバーライドしたメソッド内でオブジェクトのプロパティ値を連結します
equalsメソッド:
オーバーライドしない場合、Objectのメソッドが使用され、アドレス値が等しいか比較されます 通常、アドレス値の意味は小さいため、オブジェクトの内部プロパティ値を比較するためにオーバーライドします どちらのオブジェクトが呼び出したかによって、使用されるメソッドが異なります
cloneメソッド:
オブジェクトのクローン:Aオブジェクトのプロパティ値を完全にBオブジェクトにコピーします(オブジェクトコピーとも呼ばれます) protected属性のため、オーバーライドが必要です デフォルトで浅いクローンです
実装手順:
- Objectのcloneメソッドをオーバーライド
- JavaBeanクラスにCloneableインターフェースを実装
- 元のオブジェクトを作成しcloneを呼び出す
深いクローンと浅いクローン
浅いクローン: オブジェクト内部のプロパティが基本データ型か参照データ型かに関係なく、すべてコピーされます 基本データ型は具体的なデータがコピーされ、参照データ型は参照値がコピーされます。 Objectクラスのデフォルトは浅いクローンです
- 文字列の再利用
- 参照データ型は新しいオブジェクトが作成される
- オーバーライドまたはサードパーティツールクラスを使用
深いクローン: 基本データ型はコピーされ、文字列は再利用され、参照データ型は新しいオブジェクトが作成されます 深いクローンが必要な場合は、メソッドをオーバーライドまたはサードパーティツールクラスを使用する必要があります
Objects
Objectsはツールクラスで、いくつかの機能を実現するためのメソッドを提供します。
BigIntegerのコンストラクタ:
- BigIntegerが表す数字がlongの範囲を超えていない場合、静的メソッドで取得できます
- BigIntegerが表す数字がlongの範囲を超えている場合、コンストラクタで取得できます
- オブジェクトが作成されると、BigInteger内部の値は変更できません
- 計算を行うたびに新しいBigIntegerオブジェクトが生成されます
注意点:
- 文字列は整数である必要があり、進数と一致している必要があります
- 静的メソッド:-16から16までの範囲は事前に作成されたBigIntegerオブジェクトです。複数回取得しても新しいオブジェクトは作成されません
コンストラクタでオブジェクトを作成
BigInteger bigInt1 = new BigInteger(4, new Random);
//0~2の4乗-1の範囲で取得
//4.静的メソッドでBigIntegerオブジェクトを取得(内部で最適化されています)
BigInteger bigInt5 = BigInteger.valueOf(100);
BigIntegerの主なメソッド:
import java.math.BigInteger;
BigInteger num1 = BigInteger.valueOf(10);
BigInteger num2 = BigInteger.valueOf(5);
//メンバーメソッドでオブジェクトを作成
BigInteger num3 = num1.add(num2);
BigInteger[] resultArray = num1.divideAndRemainder(num2);
System.out.println(resultArray[0]);
System.out.println(resultArray[1]);
//resultArray[0]は商、resultArray[1]は余りです
boolean isEqual = num1.equals(num2);
BigInteger num4 = num1.pow(2);
BigInteger num5 = num1.max(num2);
System.out.println(num5 == num1); //true
System.out.println(num5 == num2); //false
BigInteger num6 = BigInteger.valueOf(2147483647L);
int intValue = num6.intValue();
BigInteger num7 = BigInteger.valueOf(200);
double doubleValue = num7.doubleValue();
BigIntegerの内部ストレージ方式
BigDecimal
小数を2進数に変換すると桁数が多くなる問題があります
- 小数の正確な計算に使用
- 非常に大きな小数を表現するために使用
//1.double型の小数を渡して作成する方法は不正確なため、推奨されません
BigDecimal dec1 = new BigDecimal(0.01);
BigDecimal dec2 = new BigDecimal(0.09);
//2.文字列で表現された小数を渡してオブジェクトを作成する方法
BigDecimal dec3 = new BigDecimal("0.01");
BigDecimal dec4 = new BigDecimal("0.09");
BigDecimal dec5 = dec3.add(dec4);
//3.静的メソッドでオブジェクトを取得
BigDecimal dec6 = BigDecimal.valueOf(1);
//1.表現したい数字が大きくない場合、doubleの範囲内であれば静的メソッドの使用を推奨
//2.表現したい数字が大きく、doubleの範囲を超える場合、コンストラクタの使用を推奨
//3.渡す値が0~10の整数の場合、既に作成されたオブジェクトが返され、新しいオブジェクトは作成されません
//1.加算
BigDecimal bdAdd1 = BigDecimal.valueOf(10.0);
BigDecimal bdAdd2 = BigDecimal.valueOf(3.0);
BigDecimal bdAdd3 = bdAdd1.add(bdAdd2);
//2.減算
BigDecimal bdSubtract = bdAdd1.subtract(bdAdd2);
//3.乗算
BigDecimal bdMultiply = bdAdd1.multiply(bdAdd2);
//4.除算
BigDecimal bdDivide = bdAdd1.divide(bdAdd2, 2, RoundingMode.HALF_UP);
System.out.println(bdDivide); //53.33
BigDecimalの内部ストレージ方式
文字単位で保存し、各文字に対応する数字を保持します
正規表現
System.out.println(qq.matches("[1-9]\\d{5,19}"));
用途1:文字列がルールを満たしているか検証 用途2:テキスト内から条件に合致する内容を検索
System.out.println("a".matches("[abc]")); // true
System.out.println("ab".matches("[abc]")); // false
System.out.println("ab".matches("[abc][abc]")); // true
System.out.println("a".matches("[a-zA-Z0-9]")); //false
System.out.println("aa".matches("[a-zA-Z]")); //false
// [a-z&&[^m-p]] aからzとmからpを除いた範囲の共通部分([a-lq-z]と同等)
System.out.println("\"");
// \はエスケープ文字で、後続の文字の本来の意味を変更します
System.out.println("2442faa".matches("\\w{6,}")); //true
System.out.println("23dF".matches("[\\w&&[^_]]{4}")); //数字と文字で、4桁である必要があります true
//正しいデータを左から右に順番に記述します
//13115252525
String phoneRegex = "1[3-9]\\d{9}";
String landlineRegex = "0\\d{2,3}-?[1-9]\\d{4,9}";
String emailRegex = "\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}){1,2}";//2565566q@qq.com 2565566q@qq.com.cn .com.cnは2回出現可能、()でグループ化
//24時間表記の正規表現
String timeRegex = "([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d";
//最適化版:
String timeOptRegex = "([01]\\d|2[0-3])(:[0-5]\\d){2}";
//身分証明番号の簡単な検証:
//18桁で、最初の17桁は任意の数字、最後の桁は数字または大文字・小文字のx
String idRegex1 = "[1-9]\\d{16}[\\dXx]";
String idRegex2 = "[1-9]\\d{16}(\\d|(?i)x)";
厳密な身分証明検証:
ウェブスクレイピング
//1.正規表現のオブジェクトを取得
Pattern pattern = Pattern.compile("Java\\d{0,2}");
//2.テキストマッチングオブジェクトを取得
//マッチングオブジェクトを使ってstrを読み取り、patternルールに一致する部分文字列を検索
Matcher matcher = pattern.matcher(textString);
//3.ループを使って取得
while (matcher.find()) {
String matchedString = matcher.group();
System.out.println(matchedString);
条件付きスクレイピング
//要件1: バージョン番号8、11、17のJavaテキストを抽出するが、バージョン番号は表示しない
//要件2: バージョン番号8、11、17のJavaテキストを抽出する。正しい抽出結果:Java8 Java11 Java17 Java17
//要件3: バージョン番号8、11、17を除くJavaテキストを抽出
String text = "Javaは95年の登場以来、多くのバージョンを経て、現在企業で最も使用されているのはJava8とJava11です。これら2つは長期サポートバージョンであり、次の長期サポートバージョンはJava17です。近い将来Java17も歴史の舞台に登場することでしょう";
//1.正規表現を定義
//?の直前のデータをJavaと解釈
//= Javaの後に続くデータを指定
//ただし、取得時には前半部分のみを取得
//要件1:
String regex1 = "((?i)Java)(?=8|11|17)";
//要件2:
String regex2 ="((?i)Java)(8|11|17)";
String regex3 ="((?i)Java)(?:8|11|17)"; //2番目の?は大文字小文字を無視することを意味し: すべてのものを取得
//要件3:
String regex4 = "((?i)Java)(?!8|11|17)";
Pattern p = Pattern.compile(regex4);
Matcher m = p.matcher(text);
while (m.find()) {
System.out.println(m.group());
}
貪欲なスクレイピング
貪欲なスクレイピング: データを抽出する際に可能な限り多くのデータを取得 非貪欲なスクレイピング: データを抽出する際に可能な限り少ないデータを取得
String regex = "ab+";//abbbbb
String nonGreedyRegex = "ab+?";//ab
正規表現の文字列メソッドでの使用
String input = "小詩詩dqwefqwfqwfwq12312小丹丹dqwefqwfqwfwg12312小恵恵";
String result1 = input.replaceAll("[\\w&&[^_]]+", "vs");
//メソッドの内部では以前と同じようにテキストパーサーオブジェクトが作成されます
//文字列の先頭から読み取り、条件に一致する部分があれば、2番目のパラメータで置換します
public String[] split(String regex)
//パラメータregexは正規表現です。現在の文字列中でregex正規表現に一致する記号を"区切り文字"として文字列を分割します。
String[] array = input.split("[\\w&&[^_]]+");
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
グループ化は小括弧です 各グループにはグループ番号(シーケンス番号)があります
- ルール1: 1から始まり、連続しています
- ルール2: 左括弧を基準に、最も左のものが第1グループ、次が第2グループ、となります 赤1 青2 緑3
キャプチャグループ:
// \\グループ番号: X番目のグループの内容を再利用します(内部使用)
String regex1 = "(.).+\\1"; //開始部分と終了部分が同じかどうかを判断
String regex2 = "(.+).+\\1";//開始部分と終了部分が同じかどうかを判断、複数文字可能
String regex3 ="((.)\\2*).+\\1";//開始部分の内部の各文字も一致する必要がある
//重複内容を一つに変更
// (.) 重複内容の最初の文字を一つのグループとして扱う
// \\1 最初の文字が再度出現することを意味する
//+ 少なくとも一度
//$1 正規表現式中の第1グループの内容を再度使用する(外部使用)
非キャプチャグループ:
//特徴: グループ番号を占有しません
//ここで\\1がエラーになる理由:(?:)は非キャプチャグループであり、グループ番号を占有しません。
//(?:) (?=) (?!) はすべて非キャプチャグループです//最初のものをより多く使用します
String regex1 ="[1-9]\\d{16}(?:\\d|x|X)\\1";// \\1でエラーが発生
String regex2 ="[1-9]\\d{16}(\\d|x|X)\\1";
時間
Dateクラス
//1.日付オブジェクトの作成方法
Date date = new Date();
Date date = new Date(指定ミリ秒値);
//2.日付オブジェクトのミリ秒値の変更方法
setTime(ミリ秒値);
//3.日付オブジェクトのミリ秒値の取得方法
getTime();
SimpleDateFormatクラス
- フォーマット: 時間を好みの形式に変換
- パース: 文字列で表現された時間をDateオブジェクトに変換
//1.引数なしコンストラクタでSimpleDateFormatオブジェクトを作成(デフォルト形式)
SimpleDateFormat sdf1 = new SimpleDateFormat();
Date d1 = new Date(0L);
String str1 = sdf1.format(d1);
System.out.println(str1);//1970/1/1 08:00
//2.引数付きコンストラクタでSimpleDateFormatオブジェクトを作成(指定形式)
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EE");
String str2 = sdf2.format(d1);
System.out.println(str2);//1970年01月01日 08:00:00 木曜日
//1."yyyy-MM-dd"形式でパースし、Dateオブジェクトに変換
String dateStr = "2000-11-11";
//2.パース
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf1.parse(dateStr);
//3.フォーマット
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日");
String result = sdf2.format(date);
System.out.println(result);
Calendarクラス
//1.カレンダーオブジェクトの取得
//注意点1: Calendarは抽象クラスで、直接newはできません。静的メソッドでサブクラスのオブジェクトを取得します
//内部仕様:
//システムのタイムゾーンに応じて異なるカレンダーオブジェクトを取得します。デフォルトで現在時刻を表します。
//時間紀元、年、月、日、時、分、秒、曜日などを配列に格納します
//注意点2:
//月の範囲は0~11です。取得した値が0の場合、実際には1月です。
//曜日: 日曜日が週の最初の曜日です 1(日曜日)
Calendar calendar = Calendar.getInstance();//オブジェクトを取得
//1: 年
//2: 月
//3: 年間の週番号
//4: 月間の週番号
//5: 月内の日付
//Calendarクラスでは、インデックスに対応する数字が定数として定義されているため、直接記述できます
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
int day = calendar.get(Calendar.DAY_OF_MONTH);
int week = calendar.get(Calendar.DAY_OF_WEEK);
//setメソッド
calendar.set(Calendar.YEAR, 2000);
calendar.set(Calendar.MONTH, 11);//12月
calendar.set(Calendar.MONTH, 12);//2001年1月
//addメソッド
calendar.add(Calendar.MONTH, 1);
calendar.add(Calendar.MONTH, -1);
JDK8で追加された時間関連クラス
//ZoneIdタイムゾーン
//1.すべてのタイムゾーン名を取得
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
System.out.println(zoneIds.size());//600
System.out.println(zoneIds);
//2.現在システムのデフォルトタイムゾーンを取得
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId);//Asia/Shanghai
//3.指定したタイムゾーンを取得
ZoneId specificZoneId = ZoneId.of("Asia/Pontianak");
//Instantタイムスタンプ
Instant now = Instant.now();
Instant instant1 = Instant.ofEpochMilli(0L);
Instant instant2 = Instant.ofEpochMilli(1000000L);
//静的メソッドはクラス名で呼び出します
Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
ZonedDateTime time3 = time2.withYear(2023); //withXxx 時間を変更する一連のメソッド
boolean result1 = instant1.isBefore(instant2); //true
boolean result2 = instant1.isAfter(instant2); //false
Instant instant3 = instant2.minusSeconds(1); //1秒減らす
//注意点:
//JDK8で追加された時間オブジェクトはすべて不変です
//時間を変更、減少、増加しても
//呼び出し元は変更されず、新しい時間オブジェクトが生成されます
//日付フォーマットクラス
//DateTimeFormatter
//時間オブジェクトを取得
ZonedDateTime zonedDateTime = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
// パーサー/フォーマッター
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EE a");
// フォーマット
System.out.println(formatter.format(zonedDateTime));
//カレンダークラス
//LocalDate
LocalDate currentDate = LocalDate.now();
getMonth()
getMonthValue()
getDayOfWeek()
isBefore()
isAfter()
withYear()
plusDays()//年月日を増加
minusYears()//年月日を減少
// 今日が誕生日かどうかを判定
LocalDate birthDate = LocalDate.of(2000, 1, 1);
LocalDate today = LocalDate.now();
MonthDay birthMonthDay = MonthDay.of(birthDate.getMonthValue(), birthDate.getDayOfMonth());
MonthDay currentMonthDay = MonthDay.from(today);
System.out.println("今日はあなたの誕生日ですか?" + birthMonthDay.equals(currentMonthDay));//今日はあなたの誕生日ですか?
//LocalTime
getMinute();
getSecond();
getNano();
//他のメソッドは上記と同様
//LocalDateTime
LocalDate birthDate = LocalDate.of(2000, 1, 1);
System.out.println(birthDate);
Period period = Period.between(birthDate, today);//2番目のパラメータから1番目のパラメータを引く
//Duration
Duration duration = Duration.between(birthDate, today);//2番目のパラメータから1番目のパラメータを引く
//変換メソッド
toDays()
toHours()
toMinutes()
toMillis()
toNanos()
//ChronoUnit
ChronoUnit.YEARS.between(birthDate, today);
ラッパークラス
ラッパークラス: 基本データ型をオブジェクトでラップする
Integer
コンストラクタと静的メソッドでオブジェクトを取得する違い
//コンストラクタは常に新しいオブジェクトを作成
Integer intObj1 = new Integer(127);
//静的メソッド: 一定の範囲内では同一のオブジェクト
Integer intObj2 = Integer.valueOf(127);
//上記はJDK5以前の方法です
Integer autoBoxedInt = 10;//オブジェクトを直接代入
Integer explicitInt = new Integer(10);
int primitiveInt = autoBoxedInt + explicitInt;
//JDK5以降、Integerとintは同じものとして扱えます
Integerのメソッド
//1.整数を2進数文字列に変換
String binaryStr = Integer.toBinaryString(100);
//注意点1:
//型変換時、括弧内のパラメータは数字のみで、他の値はエラーになります
//注意点2:
//8つのラッパークラスのうち、Character以外はすべて対応するparseXxxメソッドがあり、型変換に使用できます
String boolStr = "true";
boolean boolValue = Boolean.parseBoolean(boolStr);
System.out.println(boolValue);
//キーボード入力の改善: どんなタイプでも、一律にnextLineを使用
//特徴: 改行に遭遇すると停止します
String inputLine = scanner.nextLine();
int intValue = Integer.parseInt(inputLine);
double doubleValue = Double.parseDouble(inputLine)
演習問題175, 176