ふみぽん's diary

技術的な備忘録が主のブログ

HTTP メッセージ構成要素

HTTPメッセージ 

リクエストメッセージとレスポンスメッセージ

をまとめてHTTPメッセージという

 

リクエストメッセージ

 リクエストメッセージは、基本的に次の3つの要素から構成される。

  1. リクエストライン

  2. ヘッダ

  3. ボディ

 

1.リクエストライン

 下記3点を1行で表す。

  ・HTTPメソッド

  ・リクエス

    リクエストにはURIフラグメントをのぞいたパス以降の文字列が入る。

   リクエストは絶対URIか相対URI

  プロトコルバージョン

 

  ex ) GET  /test  HTTP /1.1

 

2.ヘッダ

 ヘッダはメッセージのメタデータ(データを記述するデータ)。
 1つのメッセージに複数のヘッダを持つことが出来る。
『 名前 』:『 値 』 の形式
 
  ex ) Host  :  exsample.jp

 

3.ボディ

 リクエストメッセージの本質的な情報が入る。


レスポンスメッセージ

 レスポンスメッセージは、基本的に次の3つの要素から構成される。

  1. スタートライン

  2. ヘッダ

  3. ボディ

 

1.スタートライン

 下記の3点を1行で表す。

  プロトコルバージョン 

  ステータスコード

  ・テキストフレーズ

   OK、NG等の情報

 

ex ) HTTP /1.1  200 OK

 

2.ヘッダ

 

3.ボディ

 

※ ヘッダとボディの間は空行で区切られる。

Java実践 インスタンスの基本操作 

f:id:fumipow2317:20190608104719p:plain

インスタンスの基本操作についての備忘録


1. インスタンス5大基本操作

1-1.オブジェクトクラスの基本機能

Javaにおいて全てのクラスは、Java.lang.Obkectクラスを継承している。

Objectクラスによるメリット

  1. 全てのクラスは、Objectクラスで定義されているメソッドを持っていることが保証される。

  2. Object型の変数には、あらゆるインスタンスを代入できる。

全てのインスタンスが使えるメソッド一覧表

メソッド 説明
toString() 文字列表現を行う
equals() 等価判定を行う
hasCode() ハッシュ値を得る
compareTo() 大小関係を判定する
clone() 複製する

2. toString()インスタンスの文字列表現

2-1.toString()メソッドについて

インスタンスの内容を読んで理解できるように文字列で表したもの(文字列表現)にするメソッド。
例えば、下記のHumanクラスのインスタンスhを生成し、System.out.println(h);を実行すると、
実行結果:Human@15db9742となる。

  1. System.out.println(h)の内部では、h.toString()が実行されて文字列表現を取得
  2. 取得した文字列表現をコンソールに出力している

⇨結果的に人が見ても意味がわからない表示になってしまっている

public class Human {

    private String name;

    public Human(String name)
    {
        this.name = name;
    }

}

2-2.toString()をオーバライドする

2-1.で記述した人が見てもわからないインスタンスの文字列表現を解決するには、
java.util.Object#toString()をHumanクラスにとって適切な適切な文字列表現になるように
オーバーライドすれば良い。

public class Human {

    private String name;

    public Human(String name)
    {
        this.name = name;
    }

    //java.util.Object#toString()をOverride
    public String toString(){
        return "名前は" + this.name + "です";
    }

}

<まとめ>

  • 新たなクラスを開発したらtoString()をオーバライドしておくことで意図した文字列表現を出力することが可能になる。

3. equals()インスタンスの等価判定

3-1.等価と等値の違い

等価とは ( equals() )

  • 指している2つのものが「同じ内容」であること。
  • 同じアドレスを指していなくてもOK。

等値とは ( ==演算子 )

  • 指しているものが「完全に同一の場所に存在」すること。
  • 同じアドレス(参照先)を指していること。

3-2.equals()をオーバーライドする

java.util.Object#equals()で等価判定を行う際に内部は、ただの等値判定でしかない。
それはクラスの開発者に「何をもって等価とするのか」ということを委ねているからである。

   //equals()のオーバライド定石方法
    public boolean equals(Object o)
    {
        //①自分自身が引数として渡された場合はtrue
        if(o == this)
        {
            return true;
        }
        //②nullが引数として渡された場合はfalse
        if(o == null)
        {
            return false;
        }
        //③比較して型が異なる場合はfalse
        //[ 変数 instanceof クラス名 ]で***クラスのインスタンスかどうか判定できる
        if(!(o instanceof Human))
        {
            return false;
        }
        //型が同じであれば比較できるように適切にキャストする
        Human h = (Human) o;
        //例として先頭と末尾の空白を削除してnameが同じであれば、等価とみなす
        if(!this.name.trim().equals(h.name.trim()))
        {
            return false;
        }
        return true;
    }

<まとめ>

  • 新たなクラスを開発したら、必ずequals()をオーバライドすること。
  • オーバライドが不要なクラス
    • 等価の判定をされることが考えられないクラス。(ビジネスロジックを担当するクラス)
    • 親クラスですでにオーバライドされていて、そのロジックを使用して問題ないクラス。

4. hashCode()インスタンスの要約について

4-1.コレクションクラスHashSetの内部構造

概要
ArrayListremove()を使って特定のインスタンスを削除しようといた場合、
インスタンスの順番にequals()で削除する対象のインスタンスかどうか判定をしているが
時間がかかり効率がとても悪い。

そこで、HashSetやHashMapのようなHash系のコレクションクラスでは、

  1. 高速だが、曖昧な方法で、各要素に「だいたい同じか?」を問い合わせる
  2. 「だいたい同じ」な要素にだけ、equals()で「厳密に同じか?」を問い合わせる

まず「だいたい同じか?」の判定方法

ハッシュ値とは:インスタンスの内容を数値(int型の整数)として要約したもの。

//ハッシュ値の条件
・ 同じ(等価:同じ参照でなくてOK)インスタンスからは、必ず同じハッシュ値が取得できること。
・異なるインスタンスからは、なるべく異なるハッシュ値が取得できること。
 (異なるインスタンスでもごく稀に同じハッシュ値になってしまうこともある)

4-2.hashCode()をオーバーライドする

全てのインスタンスにはhashCode()を呼び出したさいにハッシュ値の条件に従った値を返す義務がある。

///hashCode()のオーバーライド
public int hashCode(){
  
  //適当な初期値を決める(0以外であればなんでもいい)
  int result = 23;
  //各フィールドの影響を加える(各要素に影響を与える乗数には31がよく用いられる
  result = result * 31 + name.hashCode();
  return result;
}

<まとめ>

  • 新たなクラスを開発したら、必ずhashCode()をオーバライドすること。

5. compareTo()インスタンスの順序づけ

5-1.インスタンスの並び替え

  • Collectionクラスのsort()で中身の要素を順番に並び替えてくれる。
  • 単に「並び替えろ」とJVMに指示するだけではエラーとなってしまうので何順か定めてあげる必要あり。
  • 一般的に想定される並べ順を「自然順序づけ」をいう。

5-2.Comparableインターフェースの実装

  • あるクラスの自然順序を宣言するためには、java.lang.Comparableインターフェースを実装する。
  • このインターフェースを実装すると、compareTo()メソッドのオーバーライドが強制される。
  • compareTo()メソッドを使って自然順序づけの方法を宣言することができる。

compareTo(Object obj)メソッド: 引数で渡されたインスタンスを自分自身とを比較して、大小関係を判定する。

返却する値 条件
負の数 引数インスタンスのが大きい
0(ぜろ) 自分自身と引数インスタンスが同じ
正の数 引数のインスタンスのが大きい

Humanクラスが以下を満たすクラスであれば、Collectionsクラスのsort()は、 格納したいるインスタンスcompareTo()を呼び出して大小関係を比較しながら並び替えを実行してくれる。

  • compareTo()を持つ
  • java.lang.Comparableインターフェースを実装して「自然順序づけ」を定義している
//Comparableインターフェースを実装 (<***>は自身で決定する)
public class Human implements Comparable<Human>{

    private String name;
    private int age;

    //(この間も何か処理が記載されている)

    @Override
    public int compareTo(Human h) {
        
        if(this.age < h.age)
        {
            return -1;
        }
        if(this.age > h.age)
        {
            return 1;
        }
        return 0;
    }
}

<まとめ>

  • 開発したクラスにComparableインターフェースを実装し、compareTo()をオーバライドすることで自然順正づけで並び替えを行えるようになる。

Java実践 コレクション

コレクションについての備忘録


さまざまなデータ構造

データ構造の種類

データ構造とは、「データをどのようにまとめて扱うか」ということ。


1. データ構造の種類とjava.utilパッケージのクラス(コレクションフレームワーク

  • リスト(List):順序通りに並べて格納する。中身の重複が許される。
  • セット(Set):順序があるとは限らない。中身の重複が不可。
    • java.util.HashSet
    • java.util.LinkedHashSet
    • java.util.TreeSet
  • マップ(Map):ペアを対応付けて格納する。
    • java.util.HashMap
    • java.util.LinkedHashMap
    • java.util.TreeMap

コレクションクラスでは、「どんな型のインスタンスでも格納することができる」が
インスタンスではないものは格納できないので注意!


2 .java.util.ArrayListについて

import java.util.ArrayList;

public class Main1 {

    public static void main(String[] args)
    {

     //<String>の部分をジェネリクス表現という
     //Stringの部分で指定した型のインスタンスを格納する
        ArrayList<String> nameList = new ArrayList<String>();

        nameList.add("fumi");
        nameList.add("taka");
        nameList.add("pow");

        System.out.println(nameList.get(1));

    }
}
2-1 .要素の追加・取得・削除・調査について

要素の追加

戻り値 メソッド 意味
boolean add(インスタンスの型) リストの最後に要素を追加
void add(int, インスタンスの型) リストのint番目に要素を追加
インスタンスの型 set(int, インスタンスの型) リストのint番目の要素を上書き

要素の取得

戻り値 メソッド 意味
インスタンスの型 get(int) int番目の要素を取得

リストの調査

戻り値 メソッド 意味
int size() リストに格納されている要素数を返す
boolean isEmpty() 素数がゼロであるか判定
boolean contain(インスタンスの型) 指定要素が含まれているかどうか
int indexOf(インスタンスの型) 指定要素がリストの何番目に格納されているか

イテレータを返す

戻り値 メソッド 意味
Iterator<インスタンスの型> iterator() イテレータの取得。要素を順に処理するイテレータを返却。

要素を削除する

戻り値 メソッド 意味
void clear() 要素を全て削除する。
インスタンスの型 remove(int) int番目の要素を削除する。
2-2 .イテレータについて
Iterator< リスト要素の型  > ite = リスト変数インスタンス.iterator();

// インスタンス生成にnewしない。
// newの代わりにリスト変数インスタンスのiterator()を呼び出す。
// 矢印は、java.util.Iterator< リスト要素の型 >のインスタンスとする。
戻り値 メソッド 意味
boolean hasNext() 次の要素を指せるか調査する。指せればtrueを返却。
インスタンスの型 next() 次の要素を指して、その内容(インスタンスの型の値)を返却。

3 .3種類の方法でArrayListの要素を取り出すまとめ

ArrayList<String> nameList = new ArrayList<String>();
        nameList.add("fumi");
        nameList.add("taka");
        nameList.add("pow");

    //  1. for文
        for(int count = 0; count < nameList.size(); ++count)
        {
            System.out.println(nameList.get(count));
        }


    //  2. 拡張for文
        for(String output : nameList)
        {
            System.out.println(output);
        }


    //  3. イテレータ
        Iterator<String> ite = nameList.iterator();

//Iteratorの取得した時点では、nameListの先頭要素である0番目の要素"taka"より前をさした状態となる。

        while(ite.hasNext()){   //矢印を次に進められるならtrue

            String outputName = ite.next(); //矢印を次に進めて、取り出す

            System.out.println(outputName);
        }

4 .java.util.LinkedListについて

4-1. ArrayListとLinkedListの内部構造がの違い
  • ArrayList:それぞれの箱が整列している。
  • LinkedList:それぞれの箱自体は、バラバラに存在する。しかし、それぞれの箱は「次にどの箱と繋がるか」という連結情報を持っているので数珠つなぎになっている。
4-2. 内部構造の違いによる得意・不得意
比較項目 ArrayList LinkedList
内部構造 配列(並んだ箱) 連結リスト(数珠つなぎの箱)
add(), remove() 要素の挿入・削除 ※1 遅い 高速
get(int) 指定位置の要素の取得 ※2 高速 遅い

※1

リストの途中に要素を追加したり、削除したりするのはArrayListは苦手とする。理由は追加したり削除した要素の後ろの要素をコピーして後ろに移動するもしくは前に詰めることを玉突き方式で行う必要がある。 LinkedListが得意な理由は、要素の追加または削除があっても1つの要素の連結情報を書き換えれば良いだけなので高速に処理できる。

※2

逆にLinkedListが指定位置の要素の取得が不得意な理由は、順番を表す番号の情報を持たないため先頭から順番に数えて処理を行う必要があるため。

4-3. ざっくりとらえてどちらもList
  • ArrayListもLinkedListもjava.util.Listインターフェースを実装している。
List<String> names1 = new ArrayList<String>();

List<String> names2 = new LinkedList<String>();
  • 上記のコードでは、右辺では具体的なクラスをnewしてインスタンス生成し
    左辺では、あいまいなList型の変数を利用している。

  • newするクラスはどの実装を使うか意識する必要があるが、そのインスタンスを利用する際は「ざっくりList」と捉えて利用する方がメリットが大きい。
    例)

//メソッド1

public void outPut(ArrayList<String>) 
   //ArrayList<String>しか引数として渡せない
{
     〜なんらかの処理〜
}

//メソッド2

public void outPut(List<Strign>)    
   //ArrayList<String>もLinkedList<String>も渡せちゃう
{
     〜なんらかの処理〜
}

=== ポイント===

下記には極力あいまいな型(インターフェース型)を利用できないか検討し利用する。

  • 引数
  • 戻り値
  • ローカル変数

5 .java.util.HashSetについて

  • Setインターフェースを実装するクラスは、複数の情報を重複なく格納する集合(セット)
    というデータ構造である。

  • Setの基本特性

    • 要素の重複が許されない
    • 要素には、順序関係がない

5-1 . Setインターフェースが備えるメソッドについて

要素の追加

戻り値 メソッド 意味
boolean add(要素) セットに要素を追加

セットの調査

戻り値 メソッド 意味
int size() 格納されている要素数を返す
boolean isEmpty 素数がゼロであるかを判定
boolean contains(要素) 指定要素がセットに含まれているか判定

要素を削除する

戻り値 メソッド 意味
void clear() 要素を全て削除する
boolean remove(要素) 指定した要素を削除する

イテレータを返す

戻り値 メソッド 意味
Iterator<要素> iterator() 要素を順に処理するイテレータを返す

5-2 . Setインターフェースのメソッド注意点について

1.重複した要素は無視される

Set<String> colors = new HashSet<String>();
        colors.add("赤");
        colors.add("青");
        colors.add("黄");
        colors.add("黄");  //無視される

        System.out.println(colors.size());
// => 実行結果:3

2.要素を取得するためには、拡張for文やイテレータを使う(get()がない)

  • どのような順序で取り出すことができるかは一切確約されていない。
//拡張for文で取り出し
for(String str: colors
{
  System.out.println(str);
}

//イテレータ で取り出し
Iterator<String> ite = colors.iterator();
while(ite.hasNext())
{
    System.out.println(ite.next());
}

5-3 . LinkedHashSetとTreeSetについて

  • HashSetクラス以外にもSetインターフェースを実装しているクラスがある。
    そして、HashSetと違って要素同士の順序を保証してくれる
    • LinkedHashSet ⇨ 値を格納した順序に整列
    • TreeSet ⇨ 自然順序で整列(Stringクラスでは辞書順となる)
//LinkedHashSetクラスでデータ追加順位取り出す
        Set<String> names1 = new LinkedHashSet<String>();

        names1.add("fumi");
        names1.add("taka");
        names1.add("pow");

        Iterator<String> ite = names1.iterator();

        while(ite.hasNext())
        {
            System.out.println(ite.next());
        }

//TreeSetクラスで辞書順にデータを取り出す
        Set<String> names2 = new TreeSet<String>();

        names2.add("con");
        names2.add("app");
        names2.add("bob");

        for(String name : names2)
        {#### <b>5-1 . Setインターフェースが備えるメソッドについて</b>

<u>要素の追加</u>

|戻り値|メソッド|意味|
|----|----|----|
|boolean|add(要素)|セットに要素を追加|
            System.out.println(name);
        }

6 .java.util.HashMapについて

  • Mapとは、「キー」と「値」のペアで格納するデータ構造。
  • HshMapクラスは、java.util.Mapインターフェースを実装するクラスでよく利用される。

6-1 . HashMapクラスの利用について

Map< キーの型 , 値の型 > Map変数 =  new HashMap< キーの型 , 値の型 >();
  • HashMapクラスが備えるメソッドについて
    • 注意:Mapでは値の重複は許されるが、キーの重複は許されない!
      同じキーを指定して値をput()を使うと値が上書きされてしまうので注意すること!

要素の格納

戻り値 メソッド 意味
put(キー, 値) マップにキーと値のペアを格納

要素の取り出し

戻り値 メソッド 意味
get(キー) キーに対応する値を取得(なければnull)

マップを調査する

戻り値 メソッド 意味
int size() 格納されているペアの数を調査
boolean isEmpty() 素数がゼロであるかどうかを判定
boolean containsKey(キー) 指定したキーがマップのキーに含まれているかどうか調査
boolean containsKey(値) 指定した値がマップの値に含まれているかどうか調査

要素を削除する

戻り値 メソッド 意味
void clear() 要素を全て削除する
remove(キー) 指定したキーの値を削除する

格納されているキーの返却

戻り値 メソッド 意味
Set<キー> keySet() 格納されているキーの一覧を返す

6-2 . HashMapの中身1つずつ取り出す方法

1. Mapに格納されているキー一覧を取得
2. 各キーに対応する値を取得

HashMapは順序保証しないので毎回同じ取得順序になるとは限らない。

必要であれば、LinkedHashMapで、Mapへ追加順で取り出す。

または、TreeMapで自然順序で取り出す。(メモ:Integerだと多い順っぽい)

Map<String, Integer>  pop = new HashMap<String, Integer>();

pop.put("A市", 300);
pop.put("b市", 500);
pop.put("c市", 1000);
//c市の価を上書き
pop.put("c市", 1200);

//1.キーの一覧を取得
Set<String> keys = pop.keySet();
//2.値の取得
for(String key : keys)
{
    System.out.println(pop.get(key));
}

HTTP リクエスト・メッセージ作成までの流れ

HTTP リクエスト・メッセージ作成についての備忘録


HTTP リクエスト・メッセージを作成する

1. クライアントが入力したURLを解読する

ブラウザの最初の仕事は、クライアントがブラウザで入力したURLを分解して解読すること。

http://user:password@www.XXXcom.com:80/dir/xfile.html

↓↓↓分解↓↓↓

「http:」 => データにアクセスするための仕組み。つまりプロトコル名。

「//」 => この後に続く文字列がサーバの名前であることを表す。

「www.XXXcom.com」 => webサーバ名

「/dir/xfile.html」 => データ群(ファイル)のパス名


下記の3つは省略することが可能。
「user」 => ユーザー名 
「password」 =>  パスワード
「80」 => ポート番号

URLの末尾が「/」で終わっていたら、ファイル名が省略されたことを表し、
あらかじめ設定されているファイルにアクセスする処理となる。
あらかじめ設定しておくファイル名としては、index.html default.htmが大半。

ここまでで、使うプロトコルアクセスするwebサーバサーバ内のデータ群(ファイル)がわかる。

2. HTTPのリクエスト・メッセージをつくる

リクエスト・メッセージはフォーマットが決まっている。

  • 1行目 リクエスト・ライン

    • メソッド名とアクセスするファイル(URI)とHTTPバージョンが書かれる。
    • 1つのリクエスト・メッセージには、URIが1つしか書けない。

メソッドに関して

1.GETメソッド

  • データを読み出す役割。
  • GETコマンドの後にファイル名やプログラムを示すURIを付加する。
  • URIの後にフォームページに入力したデータを付加してサーバに送信することができる。

2.POSTメソッド

  • サーバにデータを送信する役割。
  • フォームページに入力した値をサーバに送信するときに使う。

  • 2行目〜空白行手前 リクエスト・ヘッダー

    • 1行に1つのヘッダー・フィールドを書く。
    • 付加的な細かい情報
  • 空白行後〜最後 リクエスト・ボディ

    • 送信するデータを書く。
    • GETメソッドの場合は、メソッドとURIだけでwebサーバーが何をすべきか判断できるので、
      メッセージボディに書く送信データは何もない。
    • POSTのの場合にはフォームに入力したデータなどをメッセージ・ボディにかく。

Java実践 TimeAPI (Java8)

TimeAPIについての備忘録


TimeAPI

Java8から日付関連のクラス群がjava.timeパッケージをして追加になった。  

Date,Calendarと比較すると、

  • APIがわかりやすい
  • 並行処理をしても日時情報を持つインスタンスの中身が壊れないような設計になっている

java.timeパッケージの代表的なクラス

1. Instantクラス

  • エポックからの経過時間をナノ秒数で格納する。
  • 旧来のAPIにおけるDateクラスと同じような役割。
  • ナノ秒単位で正確に瞬間を表すことができる。
//InstantはDateと同じように内部的にはlong型の情報を持つ
//Instantの生成 現在日時の取得
Instant i1 = Instant.now();

System.out.println(i1);    // =>2019-05-18T07:36:27.579Z


//Instantとlongの相互変換
Instant i2 = Instant.ofEpochMilli(31920291332L);

long l2 = i2.toEpochMilli();

2. ZonedDateTimeクラス

  • Instantクラス同様で瞬間を格納できるクラス。
  • エポックからの経過時間ではなく、
    「東京における 西暦2020年8月9日....235ナノ秒」という形式で瞬間を格納する。
  • どの都市を基準にするかを明確にするためにタイムゾーンという情報を含んでいる。
    タイムゾーンは、文字列で「Asia/Tokyo」や「Europe/London」などの表現。
  • タイムゾーンの情報は、ZoneIdクラスのインスタンスとして扱う。静的メソッドof()を利用する。
//ZoneDatedTimeの生成 現在日時取得
ZonedDateTime z1 = ZonedDateTime.now();

System.out.println(z1);    // =>2019-05-18T16:42:25.140+09:00[Asia/Tokyo]


//「東京時間 西暦2020年8月9日12時30分45秒60ナノ秒」を指定して取得
ZonedDateTime z2 = ZonedDateTime.of(2020, 8, 9, 12, 30, 45, 60, ZoneId.of("Asia/Tokyo"));

System.out.println(z2);// =>2020-08-09T12:30:45.000000060+09:00[Asia/Tokyo]
//InstantとZonedDateTimeの相互変換
Instant i3 = z2.toInstant();
ZonedDateTime z3 = i3.atZone(ZoneId.of("Europe/London"));

3. LocalDateTimeクラス

  • ZonedDateTimeクラスと似ているが、タイムゾーン情報だけは保存しない。
  • タイムゾーンの情報を保存しないことで、
    「どの瞬間か」確定できないが曖昧な時間情報を保持することができる。
//LocalDateTimeの生成方法
LocalDateTime l3 = LocalDateTime.now();
System.out.println(l3);  // =>2019-05-18T18:08:10.764

//「西暦2020年8月9日12時30分45秒60ナノ秒」を指定して取得
LocalDateTime l4 = LocalDateTime.of(2020, 8, 9, 12, 30, 45, 60);
System.out.println(l4);  // =>2020-08-09T12:30:45.000000060


//LocalDateTimeとZonedDateTimeの相互変換
ZonedDateTime z4 = l4.atZone(ZoneId.of("Asia/Tokyo"));
LocalDateTime l5 = z4.toLocalDateTime();
特定日時を指し示すクラスで共通して利用されるインスタンス生成メソッド(静的)
メソッド名 解説
now() 現在日時からインスタンスを生成する
of()/of~() 他の種類から変換してインスタンスを生成する
parse() "2020年8月9日"等の文字列からインスタンスを生成する

4. DurationクラスとPeriodクラス

  • 「2つの日付の間隔」と「2つの時刻の間隔」を表すクラス。
  • 「時・分・秒」の単位の比較的短い間隔を表す場合は、Durationクラスを使う。
  • サマータイム閏年などを考慮しながら日数期間を管理する場合は、Periodクラスを使う。
  • 両クラスとも、静的メソッドbetween(),ofDays(),ofMonths()を使うことでインスタンスを取得する。
LocalDate d1 = LocalDate.of(2020, 8, 9);
LocalDate d2 = LocalDate.of(2020, 8, 19);

//10日間を表す方法を生成
Period p1 = Period.ofDays(10);
Period p2 = Period.between(d1, d2);

//d2にさらに10日間プラス
LocalDate d3 = d2.plus(p2);
System.out.println(d3);

Java実践 日付取り扱いの基本[Date型について]

日付取り扱いのまとめ


日付取り扱いの基本

Date型について

  • java.util.Dateクラスは日付を扱い際によく利用される。
  • エポック(1970/1/1/00:00)からの経過ミリ秒数をlong値で保持している。
  • 引数なしでnewすると現在の日時情報がインスタンス(のfasttime)に格納される。
import java.util.Dafe;

Date now = new Date() ;
  • long値を引数にしてnewすると指定日時情報がインスタンスに格納される。
Date now = new Date(1316622225935L);
  • getTime() setTimeで、インスタンス内に保持される日時情報をlong値で取得・設定できる。
    取得するまたは設定するlong値はエポックからのミリ秒数である。
Date t = new Date();                        
// => 現在日時取得
t.getTime();
// => エポックから現在時点のミリ秒数をlong値で取得
t.setTime(1316622225935L);               
// => エポックから1316622225935Lミリ秒の時点を表すように設定
t.getTime();
// => 保持されているエポックからのミリ秒数を表すlong値を取得

日時のlong値について

日時をlong値で扱う方法

Date now1 = new Date();
long now2= System.currentTimeMillis();

System.out.println("Dateをnew : " + now1);
System.out.println("currentTimeMillisメソッド : " + now2);

//実行結果
//Dateをnew : Sat May 18 12:25:46 JST 2019
//currentTimeMillisメソッド : 1558149946137
//

この2通りは実行結果こそ違うが内部的には、long値である。

Dateクラスの課題

エポックからのミリ秒数をlong値で扱うため、人が扱いにくい。。。

Dateクラスの課題についての対策

1.「年・月・日・時・分・秒」の6つの情報で扱う

  • java.util.Calendarクラスで人が認識しやすい形式で表示する。
  • Calendarクラスを用いて「月」を表す場合、0〜11で12ヶ月を表す。
//Dateインスタンスから6つのint値「年・月・日・時・分・秒」を生成

Date now = new Date();
Calendar c = Calendar.getInstance();
c.setTime(now);

int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);
int hour = c.get(Calendar.HOUR);
int minute = c.get(Calendar.MINUTE);
int second = c.get(Calendar.SECOND);

System.out.println("今年は" + year +"です");
//6つのint値「年・月・日・時・分・秒」からDateインスタンスを生成

Calendar c = Calendar.getInstance();

//2020年8月9日12時30分45秒を設定
c.set(2020, 7, 9, 12, 30, 45);

//上記で設定した日時の値を持つDateインスタンスの生成
Date future = c.getTime();

2.「西暦2020年8月9日」のように扱う

  • 独自に書式を指定して日時を表す場合は、java.text.SimpleDateFormatを用いる。
Date now = new Date();
//指定した書式でDateインスタンスを変換
SimpleDateFormat f = new SimpleDateFormat("西暦yyyy年MM月dd日");
String formatDate = f.format(now1);
SimpleDateFormat f = new SimpleDateFormat("西暦yyyy年MM月dd日");
//指定した文字列でDate型変数を取得する
Date d = f.parse("西暦2020年8月9日");

DateやCalendarクラスでの問題点と機能的限界

1.問題点

  • 12ヶ月を0~11で表す等の紛らわしさがある。
  • 並列処理(異なるスレッドで同時に処理)していると変数の中身が異常な値になることがある。

2.機能的限界

  • 最小でもミリ秒単位でしか時間を扱えない。
  • タイムゾーンを考えない曖昧な時間を表せない。
  • 時間の幅を表せない。

Java実践 正規表現の活用

正規表現の活用についての備忘録

正規表現の活用

正規表現の基本文法

1.通常の文字:その文字でなければならない

String text = "Fumi"  

text.matches("Fumi")              // => true
text.matches("fumi")              // => false
text.matches("FumiFumi")          // => false

2.ピリオド「 . 」:任意の1文字であれば良い

パターン中にピリオド記号が含まれている場合は、 その部分には任意の1文字(なんでもいいので必ず1文字)があれば良いという意味する。

"World".matches("Wor.d")           // => true

3.アスタリスク「 * 」:直前の文字の0回以上の繰り返し

パターン中にアスタリスク記号が含まれていた場合は、 その直前の文字の0回以上の繰り返しを意味する。

"Doooooog".matches("Do*g")        // => true 
"Abcde123".matches(".*")          // => true

正規表現 ".*" は、任意の1文字を0回以上繰り返す事を表す

text.matches("fu.*");  
// fuで始まる任意の文字列( text.startsWith("fu")の代わりになる)

text.matches(".*mi");
//miで終わる任意の文字列(text.endsWith("mi")の代わりになる)

4. 波カッコ:指定回数の繰り返し

パターン中に波括弧で囲まれた数字が登場した場合、直前の文字の指定回数の繰り返しを意味する。

"fumi{2}123"  => "fumifumi123"

5. 角カッコ:いずれかの文字

パターン中に各括弧( [ ] )で囲まれた部分がある場合、各括弧の中のどれか1文字に当てはまる事を要求する意味となる。

"UR[LIN]"
=>「1文字目がU、2文字目がR 、3文字目がLかIかNである事」

6. 角カッコ内のハイフン:指定範囲のいずれかの文字

角カッコ中にハイフン記号がある場合、その両端にある文字を含む範囲の任意の1文字である事を意味する。

"url".matches([a-z]{3})   // => true

↓定義されている文字クラス↓

パターン記号 意味
¥d いずれかの数字 ([0-9] と同じ)
¥w 英字・数字・アンダースコア ( [ a-zA-Z_0-9] と同じ)
¥s 空白文字

7. ハットとダラー:先頭と末尾

パターン中のハット記号(^)は文字列の先頭を、ダラー記号($)は文字列の末尾を表す。

"^j.*h$"    =>   「先頭がjで末尾がhの任意の長さの文字列」

おまけ1. split()メソッド:文字列の分割

split()メソッドを使うと、1つの文字列を複数に分割できる。

String text = "abc, def:ghi"
String[] words = text.split("[,:]");
for(String word : words)
{
      System.out.print(word + "->");
}
// 実行結果 =>  abc->def->ghi->

おまけ2.replaceAll()メソッド:文字列の置換

replaceAll()メソッドを使うと、文字列の中でパターンに一致した箇所を別の文字列に置換できる。

String text = "abc, def:ghi"
String word = text.replaceAll("[beh]","X");
System.out.println(word);
// 実行結果 =>  aXc,dXf:gXi