20201015のJavaに関する記事は8件です。

Java APIをラムダ式を使って使用する方法

このサイトが分かりやすかったナリ
https://employment.en-japan.com/engineerhub/entry/2019/04/25/103000

リストのsortメソッドの引数に、変数宣言なしでラムダ式を入れていたのがいまいち理解できなかったので調べた。

匿名クラスでメソッドをオーバーライドする代わりに、ラムダ式を使うという当たり前のことだが、したの説明を見てなんとなく納得したナリ

上記サイトから引用

new Predicate<Integer>() {
    @Override
    public boolean test(Integer number) {
        return Math.abs(number) >= 5;
    }
}

そして、この処理はラムダ式で置き換えることができ、次のコードのように記述することができます。

number -> Math.abs(number) >= 5
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】コレクションクラスのSet構造(HashSetとTreeSetについて)

プログラミング勉強日記

2020年10月15日
JavaでTreeSetを使ったが、HashSetとの違いがよくわからなかったので、記録する。

コレクションクラスとは

 コレクションは要素を集めたオブジェクトのこと。コレクションクラスは大きく分けてList,Map,Setの3つの種類がある。それぞれ性質の異なるクラスに分かれている。

 List構造はArrayListとLinkedListの2種類ある。List構造は要素を順番付けして管理する構造で、要素はインデックス番号順に並んでいるので、番号を指定して要素の取得や挿入、更新、変更などができる。

 Map構造はHashMapとTreeMapの2種類ある。Map構造はキーと値をセットにしたものを1つの要素として管理するデータ構造で、要素がキーとして管理されているのでキーを指定して値の更新や削除をお来ぬことができる。
 今回扱うHashSetとTreeSetは名前からもある通りSet構造であり、下記にまとめる。

Set構造のコレクションクラスとは

 Set構造はHashSetとTreeSetの2種類あり、要素を順番付けしないで管理するデータ構造である。Listのような順番付けやMapのようなキー管理もないので要素の取得にはIteratorや拡張for文で取得する。要素の重複はできない(同じキーがセットされた場合は上書きする。)
 HashMapとTreeSetの違いを簡単にまとめると以下のようになる。

  • HashMapは取得順は関係ない
  • TreeSetはソートされた順で要素の取得ができる
  • HashMapはnullを扱えない
  • TreeSetはnullを扱える

 HashMapは要素の取得順は保証されないが、TreeSetは自動ソートされて管理されるのでソートされた順番で要素が取得できる。また、HashMapは要素にnullを使用することができるが、TreeSetはnullを使用することができる。

まとめ

 Set構造だけでなくコレクションクラスの特徴を表で簡単にまとめる。

ArrayList LinkedList HashMap TreeMap HashSet TreeSet
インタフェース List List Map Map Set set
要素の重複 × × × ×
nullの要素 × × ×
自動ソート × × ×

 上では述べていないが、ArrayListはよその取得が早いが、挿入や削除が遅く、LinkedListは要素の挿入や削除は早いが取得は遅いという特徴がある。

参考文献

TreeSetクラス
コレクションクラスの比較
 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Java の Stream で List を List<String> に変換するサンプルコード

// List に入れる要素のクラス
public class MyData {

  public final String name;
  public final Integer age;

  public MyData(String name, Integer age) {
    this.name = name;
    this.age = age;
  }

  public String getMyInfo() {
    return name + "(" + age + ")";
  }
}
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class Main {

  public static void main(String[] args) {

    // データを構築
    List<MyData> list = new ArrayList<>() {
      {
        add(new MyData("Alice", 88));
        add(new MyData("Bob", 8));
        add(new MyData("Carol", null));
        add(null);
      }
    };

    // 変換例1
    List<String> list1 = list.stream() // Stream オブジェクトを生成
      .filter(Objects::nonNull)        // 要素が null のものを排除
      .map(MyData::getMyInfo)          // 要素ごとに文字列を生成
      .collect(Collectors.toList());   // List 化
    System.out.println(String.join("\n", list1));

    // 変換例2
    List<String> list2 = list.stream()                // Stream オブジェクトを生成
      .filter(Objects::nonNull)                       // 要素が null のものを排除
      .map(mydata -> mydata.name + ": " + mydata.age) // 要素ごとに文字列を生成
      .collect(Collectors.toList());                  // List 化
    System.out.println(String.join("\n", list2));

    // 変換例3
    List<String> list3 = list.stream() // Stream オブジェクトを生成
      .filter(Objects::nonNull)        // 要素が null のものを排除
      .map(mydata -> {                 // 要素ごとに文字列を生成
        if (mydata.age == null) {
          return mydata.name;
        } else {
          return mydata.name + ": " + mydata.age;
        }
      })
      .collect(Collectors.toList());   // List 化
    System.out.println(String.join("\n", list3));
  }
}

Java 15 (AdoptOpenJDK 15+36) による実行結果。

$ javac *.java
$ java Main
Alice(88)
Bob(8)
Carol(null)
Alice: 88
Bob: 8
Carol: null
Alice: 88
Bob: 8
Carol

参考: Stream (Java Platform SE 8 )

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaでEmail送信を実装する

はじめに

SpringBootのプロジェクトでパスワードを再設定したかったのですが、初期化したパスワードをEmailで送信できないか実践してみた備忘録です。

まずは環境設定

環境は
IDE:Eclipse
バージョン:Java8、springframework.boot version 2.3.0

また、メール送信のためにはSMTPサーバーが必要ですが、ローカルだと実際に送信できなさそうなので、今回は簡単にGoogleのSMTPを使用します。

build gradleに必要なものをビルド

build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-mail'
    // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
    // パスワードの文字列をランダム生成するためのcommons-lang3をコンパイル
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.10'
}

application.propeties

<!-- Gmailsmtpの設定 -->
spring.mail.host=smtp.gmail.com
spring.mail.port=587

<!-- ローカルsmtpの設定 -->
<!-- spring.mail.host=localhost -->
<!-- spring.mail.port=25 -->

spring.mail.username=*****@*****
spring.mail.password=******
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

usernameに送信元のメールアドレス、passwordはそのメールアドレスを持つgoogleアカウントのパスワードを記述。
コメントにも書いてありますが、ローカル環境でしたらhostをlocalhostにし、既定のport番号を記述すればよいです。

viewやらcontrollerやらを作成

htmlにはpostメソッドを指定したインプットformを作成。メールアドレスを記述して送信ボタンを押下すれば、そのアドレスにメールが送信されるようにします。(本筋ではないので割愛)

Controller

import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import com.example.demo.entity.User;
import com.example.demo.service.UserService;

@Controller
@RequestMapping("passReset")
public class PassResetController {
    @Autowired
    private UserService userService;
    @Autowired
    private MailSender mailSender;

    @GetMapping
    public ModelAndView passResetPage(ModelAndView mav) {
        return mav;
    }

    @PostMapping
    public ModelAndView passResetSend(@RequestParam(name = "email") String email,
                                                                User user,
                                                                ModelAndView mav) {
        SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
        simpleMailMessage.setTo(email);
        user = userService.findUserByEmail(email);
        if (user == null) {
            simpleMailMessage.setTo(email);
            simpleMailMessage.setSubject("パスワード再設定のお知らせ");
            simpleMailMessage.setText("**サービスです\n\r\n\r" + email + "\n\r\n\rこちらのアカウントは存在しません");
            this.mailSender.send(simpleMailMessage);
            mav.setViewName("redirect:login");
            return mav;
        }
        String password = RandomStringUtils.randomAscii(8);;
        userService.accountEdit(user.getEmail(), password);
        simpleMailMessage.setTo(email);
        simpleMailMessage.setSubject("パスワード再設定のお知らせ");
        simpleMailMessage.setText("**サービスです\n\r\n\r" + email + "\n\r\n\rこちらのアカウントのパスワードを再設定しました。\n\r\n\r再設定パスワード:" + password + "\n\r\n\rログイン後、パスワードをご自身で再設定してください。");
        this.mailSender.send(simpleMailMessage);
        mav.setViewName("redirect:login");
        return mav;
    }
}

postメソッドで行なっていることは、
1. viewから送られてきたメールアドレスでDBにアクセス、ユーザーを検索
2. ユーザーが存在しなければ、アカウントが存在しないことをメール本文で記載
3. ユーザーが存在した場合は、パスワードをランダムで生成(RandomStringutils.randomAscii)し、DBにあるユーザーのパスワードを変更
4. 変更されたパスワードを平文のままメール本文に記載

の流れとなります。

この実装の注意点

本当はRandomStringUtilsではなく、UUIDを使用したほうがセキュリティ的にもよいのでしょうが、記号などの扱いを考えるとStringUtilsの方が簡単かなと思い、こちらを使用しました。
また、Googleアカウントで2段階認証を設定しているとアプリケーションがログインできないので、こちらはあらかじめ無効にしておく必要があります。

まとめ

と、こんな感じでセキュリティ的にはがばがばですが、なんとなく流れは掴めたように思います。
ローカルのSMTPサーバーでもやってみましたが、同じ方法で(設定は多少違いますが)サーバーに送信されたメールが確認できたので、ローカル環境ではこのくらいが現実的な範囲かなーと感じました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

java mail pop3 imap 受信

メモ
受信のみ。送信はこちらを参考:https://qiita.com/rubytomato@github/items/b106ff8011bcad60bce2

pom.xml
    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.sun.mail/javax.mail -->
        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>1.6.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.13.1</version>
        </dependency>
    </dependencies>
Mail.java
package jp.co.syslinks.ga;

import java.io.IOException;
import java.util.Properties;

import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.MimeMultipart;

public class Mail {

    public static void main(String[] args) throws Exception {
        String host = "pop.mail.yahoo.com";
        String user = "USERNAME";
        String password = "PASSWORD";

        Properties properties = System.getProperties();
        properties.setProperty("mail.store.protocol", "imap");
        Session session = Session.getDefaultInstance(properties);
        Store store = session.getStore("pop3");
        store.connect(host, user, password);
        Folder inbox = store.getFolder("Inbox");
        inbox.open(Folder.READ_ONLY);

        Message[] messages = inbox.getMessages();
        for (int i = messages.length - 3; i < messages.length; i++) {
            System.out.println("Message " + (i + 1));
            System.out.println("From : " + messages[i].getFrom()[0]);
            System.out.println("Subject : " + messages[i].getSubject());
            System.out.println("Sent Date : " + messages[i].getSentDate());
            System.out.println("Body : " + getTextFromMessage(messages[i]));
            System.out.println();
        }
        inbox.close(true);
        store.close();
    }

    static private String getTextFromMessage(Message message) throws MessagingException, IOException {
        String result = "";
        if (message.isMimeType("text/plain")) {
            result = message.getContent().toString();
        } else if (message.isMimeType("multipart/*")) {
            MimeMultipart mimeMultipart = (MimeMultipart) message.getContent();
            result = getTextFromMimeMultipart(mimeMultipart);
        }
        return result;
    }

    static private String getTextFromMimeMultipart(MimeMultipart mimeMultipart) throws MessagingException, IOException {
        String result = "";
        int count = mimeMultipart.getCount();
        for (int i = 0; i < count; i++) {
            BodyPart bodyPart = mimeMultipart.getBodyPart(i);
            if (bodyPart.isMimeType("text/plain")) {
                result = result + "\n" + bodyPart.getContent();
                break; // without break same text appears twice in my tests
            } else if (bodyPart.isMimeType("text/html")) {
                String html = (String) bodyPart.getContent();
                result = result + "\n" + org.jsoup.Jsoup.parse(html).text();
            } else if (bodyPart.getContent() instanceof MimeMultipart) {
                result = result + getTextFromMimeMultipart((MimeMultipart) bodyPart.getContent());
            }
        }
        return result;
    }
}

参考になったサイト
http://alvinalexander.com/java/javamail-pop-pop3-reader-email-inbox-example/
https://stackoverflow.com/questions/11240368/how-to-read-text-inside-body-of-mail-using-javax-mail

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

最初に知っておくべきJavaの基本文法

はじめに

この記事は以下のような方が読まれることを想定しています。

  • 今度実務でJavaを使うことになったが、Javaなんて学生時代にやって以来忘れてしまった。
  • C言語など他言語のプログラミング経験はあるが、Javaは初めてだ。
  • オブジェクト指向よりも基本的な文法を復習したい。

mainメソッドを書いて動かしてみよう

サイトや本を読むだけでは理解は進みません。
自分でコードを書いて、プログラムを動かすことがとても大事です。

1. mainメソッドのポイント

  • mainメソッドは、何か1つのクラス(例:Sample1)に必ず属さないといけない。
  • アクセス修飾子publicは、「どこからでも呼び出せる」という意味。
    • Javaのメイン関数は public と決まっている。
  • staticは、クラスのインスタンス化せずにmainメソッドを呼び出すために付けます。
  • 戻り値はvoid、つまりmainメソッドは何も返さないという意味。
  • mainの括弧の中に書いた「String[] args」
    • String[]はStringの配列という意味
    • Stringは文字列を格納するための型。参照型に分類されるもの。
    • argsは引数名。コマンドライン引数で渡された値をプログラム内で使うことができる。
  • クラスやメソッドは {} で括る。
  • System.out.print()で標準出力する。
  • 実行文は ; で終わる。
  • // はコメント行。プログラム実行時には無視される。

プログラム例

Sample1.java
public class Sample1 {
    public static void main(String[] args){
        // ここで標準出力する
        System.out.print("hello world");
    }
}

2. プログラムを実行

  • ファイル名(Sample1.java)、クラス名(Sample1)を同じにする。
  • プログラム実行は「java Sample1 .class」ではないことに注意。
  • プログラム実行後、mainメソッドが最初に実行される。

実行例

> javac Sample1.java  # コンパイル
> java Sample1        # プログラム実行

hello world       # 実行結果

リテラル

ポイント

  • リテラルとは、文字や数値といった値そのもののこと。

プログラム例

Sample2.java
public class Sample2 {
    public static void main(String[] args){
        // 1. 文字リテラル
        System.out.println('A');

        char c1 = 'B';
        System.out.println(c1);     // 変数

        //System.out.println('AB');  // コンパイルエラー

        System.out.println('\u0041');// 文字コード指定

        // 2. 文字列リテラル
        System.out.println("Hello");

        String str = "123";
        System.out.println(str);

        // 補足: エスケープシーケンス
        System.out.println("Hello\nWorld!!");

        // 3. 整数リテラル(10進数)
        int i = 123;
        System.out.println(i);
        System.out.println(i+100);

        // 4. 浮動小数点数リテラル
        double d = 3.14;
        System.out.println(d);
        System.out.println(d+1.54);
        d = 2.712e-4;
        System.out.println(d);

        // 5. 論理値リテラル
        boolean b = true;
        System.out.println(b);
        b = (10 == 5);
        System.out.println(b);

    }
}

演算子

ポイント

  • 算術演算子(+, -, *, / など)
  • 代入演算子
  • 比較演算子
  • 論理演算子
  • ビット演算子
  • 演算子の優先順位

プログラム例

Sample3.java
import java.util.Arrays;  // 配列の中身を表示するため

public class Sample3 {
    public static void main(String[] args){
        System.out.println("======= 1. 算術演算子 =======");
        // 1.1 インクリメント
        int a = 10;
        int b = a++;            // 代入後にインクリメント
        System.out.println(b);  // int b = a;
                                // a = a + 1;
                                // と同じ

        int x = 10;
        int y = ++x;            // 代入前にインクリメント
        System.out.println(y);  // x = x + 1;
                                // int y = x;
                                // と同じ

        // 1.2 文字列の連結
        String str1 = "Hello " + "World";
        System.out.println(str1);

        System.out.println("======= 2. 代入演算子 =======");
        // 2.1 代入(プリミティブ型)
        int x2 = 10;
        int y2 = x2;
        y2 += 1;
        System.out.println(x2);  // 結果:10
        System.out.println(y2);  // 結果:11

        // 2.2 代入(参照型)
        int[] x3 = { 10, 20, 30 };
        int[] y3 = x3;
        y3[0] += 1;
        System.out.println(Arrays.toString(x3)); // 結果:[11, 20, 30]、x[0]の値も変わることに注意!!
        System.out.println(Arrays.toString(y3)); // 結果:[11, 20, 30]

        System.out.println("======= 3. 比較演算子 =======");
        // 3.1 数値の比較(基本型, 参照型)
        int[] x4 = { 1, 2, 3 };
        int[] y4 = { 1, 2, 3 };
        System.out.println(x4[0] == y4[0]);         // 基本型の比較 (結果:true)       
        System.out.println(x4 == y4);               // 参照型の比較1(結果:false)   
        System.out.println(Arrays.equals(x4, y4));  // 参照型の比較2(結果:true)   

        // 3.2 文字列の比較
        String str2 = "abc";
        String str3 = "ab";
        str3 += "c";
        System.out.println(str2==str3);         // 結果:false
        System.out.println(str2.equals(str3));  // 結果:true

        System.out.println("======= 4. 論理演算子 =======");
        System.out.println("======= 5. ビット演算子 =======");
    }
}

変数宣言

ポイント

  • 変数宣言と初期化を別々にやる記述と、同時にやる記述がある。

別々にやる記述の例

Sample5.java
public class Sample5 {
    public static void main(String[] args){
        // 1. 変数宣言
        // [書式] データ型名 変数名;
        int idata;
        String str;

        // 2. 値の代入
        // [書式] 変数名 = 値;
        idata = 100;
        str = "abcdef";

        // 代入は「==」ではないことに注意!
        // idata == 100;はコンパイルエラーになる

    }
}

同時にやる記述の例

Sample6.java
public class Sample6 {
    public static void main(String[] args){
        // 1. 変数宣言と値の代入
        // [書式] データ型名 変数名 = 値;
        int idata = 100;
        String str = "abcdef";
    }
}

プリミティブ型(基本データ型)

ポイント

  • プリミティブ型とは、Javaの基本となる変数の型。
  • 後述の「参照型」と区別される。
  • プリミティブ型の8種類
    • 整数
      • byte型
        • 8ビット(1バイト)のデータ
        • -128~127の整数
      • short型
        • 16ビットのデータ
        • -32768から32767までの整数
      • int型
        • 32ビットのデータ
        • -2147483648から2147483647までの整数値
      • long型
        • 64ビットのデータ
        • -9223372036854775808から9223372036854775807までの整数値
    • 浮動小数点数
      • float型
        • 32ビットの単精度浮動小数点数
        • 有効桁数は6桁
      • double型
        • 64ビットの倍精度浮動小数点数
        • 有効桁数は15桁
    • 論理型
      • boolean型
        • 真偽値(trueかfalse)
    • 文字
      • char型
        • 16ビットのUNICODE文字1文字
        • 実際は、16ビットの符号なし整数(文字コード)を格納する

プログラム例

Sample4.java
public class Sample4 {
    public static void main(String[] args){
        System.out.println("======= 1. byte型 =======");
        byte b1 = 127;
        System.out.println(b1);     
        b1 += 1;
        System.out.println(b1);     // -128になってしまう(オーバーフロー)

        System.out.println("======= 2. short型 =======");
        short s1 = -32768;
        System.out.println(s1);     
        s1 -= 1;
        System.out.println(s1);     // 32767になってしまう(オーバーフロー)

        System.out.println("======= 3. int型 =======");
        int i1 = s1;
        i1 += 1;
        System.out.println(i1);     // 32768(正しい)

        System.out.println("======= 4. long型 =======");
        //long l1 = 9223372036854775807;    // コンパイルエラー
        long l1 = 9223372036854775807L;     // 正しい
        System.out.println(l1);

        System.out.println("======= 5. float型 =======");
        //float f1 = 3.14;  // コンパイルエラー
        float f1 = 3.14F;   // 正しい
        System.out.println(f1);

        System.out.println("======= 6. double型 =======");
        double d1 = 3.14; 
        d1 = d1 + 5.2e3;
        System.out.println(d1);

        System.out.println("======= 7. boolean型 =======");
        boolean bl1 = true;
        System.out.println(bl1);
        bl1 = (d1 < 3);             // d1は3より大きいので、演算結果はfalse
        System.out.println(bl1);

        System.out.println("======= 8. char型 =======");
        char c1 = 'a';
        char c2 = 'あ';
        //char c3 = "ab";       // コンパイルエラー: 文字列は格納できない
        System.out.println(c1);
        System.out.println(c2);
    }
}

参照型

ポイント

  • Javaは、プリミティブ型以外の変数の型は「参照型」と分類される。
  • 参照型の代表例は「String」

プログラム例

Sample7.java
public class Sample7 {
    public static void main(String[] args){
        String str = "Hello";   // 文字列は "(ダブルクォーテーション)で括る

        str += "World!!";

        System.out.println(str);// "HelloWorld!!"と表示

    }
}

プリミティブ型と参照型の違いは?

ポイント

  • どちらも「変数の型」を表すもの。
  • 違いは「変数に入れる値」。
    • プリミティブ型は、変数には「値」そのものを入れている。
      • 整数ならば100, 200, 0など
      • 文字ならば’a’, 'あ'など
      • 論理型ならtrue, false
    • 参照型は、変数には「メモリのアドレス値(値が入っているメモリの場所)」を入れている。
      • 文字列型Stringならば、文字列"abcdef"があるアドレス値(1000番地など)

プログラム例

Sample8.java
public class Sample8 {
    public static void main(String[] args){
        // プリミティブ型
        int x = 10;
        int y = x;

        // 参照型
        String s1 = "abc";
        String s2 = s1;
    }
}

プリミティブ型の変数に入っているものは「値」そのもの

image.png

参照型の変数に入っているものは「メモリのアドレス値」

1000番地には文字列"abc"が入っている。
image.png

配列

プログラム例1

Sample9.java
public class Sample9 {
    public static void main(String[] args){
        // 1. 配列の変数宣言
        // [書式] データ型名[] 配列名;
        int[] ai;
        String[] as;

        // 2. 配列の領域確保
        // [書式] 配列名 = new 型名[要素数];
        ai = new int[5];
        as = new String[10];

        // 3. 配列の初期化
        // [書式] 配列名[要素番号] = 初期値;
        // 注意:要素番号は「0」から始まる
        ai[0] = 1;
        ai[1] = 2;
        as[0] = "abc";
        as[1] = "defg";
    }
}

プログラム例2

Sample10.java
public class Sample10 {
    public static void main(String[] args){
        // 方法1:配列の変数宣言と領域確保を1つにまとめる
        // [書式] データ型名[] 配列名 = new 型名[要素数];
        int[] ai1 = new int[5];
        String[] as1 = new String[10];

        // 方法2:配列の変数宣言, 領域確保, 初期化を1つにまとめる
        // [書式] データ型名[] 配列名 = {初期値1, 初期値2, ・・・};
        int[] ai2 = {1, 2, 3};
        String[] as2 = {"abc", "de", "fghij"};
    }
}

プログラミングの三大要素って知っていますか?

  • 順次処理(逐次処理)
  • 条件分岐
  • 繰り返し処理(反復処理)

Javaに限らず、全プログラミング言語で共通する重要な概念です。

1. 順次処理(逐次処理)

プログラムの上(先頭)から下(末尾)に処理が順番に実行されること。

プログラム例1

Sample12.java
public class Sample12 {
    public static void main(String[] args){
        // 実行結果は、何度やっても「1, 2, 3, 4, 5」の順番で表示される
        System.out.println("1"); 
        System.out.println("2"); 
        System.out.println("3"); 
        System.out.println("4"); 
        System.out.println("5"); 
    }
}

プログラム例2

Sample13.java
public class Sample13 {
    public static void main(String[] args){
        // メソッドを呼び出しても同じ。
        // 実行結果は、何度やっても「1, 2, 3, 4, 5」の順番で表示される。
        System.out.println("1"); 
        sub();
        System.out.println("5"); 
    }

    public static void sub(){
        System.out.println("2"); 
        System.out.println("3"); 
        System.out.println("4"); 
    }
}

2. 条件分岐

いわゆるif文やswitch文のこと。
ある条件に当てはまるときと当てはまらないときで、別々の処理をさせたいときなど、プログラムの流れを変えるときに使う。

プログラム例

Sample14.java
// 実行結果
// iは偶数です。
// jは奇数です。
// kは偶数、かつ10以下。
// ニ
public class Sample14 {
    public static void main(String[] args){
        int i = 10;
        int j = 9;
        int k = 8;
        int l = 2;

        // 1.1 if文
        if(i % 2 == 0){
            System.out.println("iは偶数です。"); 
        }

        // 1.2 if-else文
        if(j % 2 == 0){
            System.out.println("jは偶数です。"); 
        }else{
            System.out.println("jは奇数です。"); 
        }

        // 1.3 if-elseif文
        if(k % 2 == 0 && k > 10){
            System.out.println("kは偶数、かつ10より大きい。"); 
        }else if(k % 2 == 0 && k <= 10){
            System.out.println("kは偶数、かつ10以下。"); 
        }else{
            System.out.println("kは奇数です。"); 
        }

        // 2 switch文
        switch (l){
        case 0:
            System.out.println("ゼロ"); 
            break;
        case 1:
            System.out.println("イチ"); 
            break;
        case 2:
            System.out.println("ニ"); 
            break;
        default:
            System.out.println("その他"); 
            break;
        }
    }
}

3. 繰り返し処理(反復処理)

いわゆるfor文やwhile文のこと。
ある処理を繰り返すときに使う。

プログラム例

Sample15.java
// 実行結果
//  [100, 100, 100, 100, 100, 100, 100, 100, 100, 100]
//  [200, 200, 200, 200, 200, 200, 200, 200, 200, 200]
//  [300, 300, 300, 300, 300, 300, 300, 300, 300, 300]
import java.util.Arrays;

public class Sample15 {
    public static void main(String[] args){
        int[] ai = new int[10];

        // 1. for文:配列の全要素に 100 を設定
        for(int i = 0; i < ai.length; i++){
            ai[i] = 100;
        }
        System.out.println(Arrays.toString(ai)); 

        // 2. while文:配列の全要素に 200 を設定
        int j = 0;
        while(j < ai.length){
            ai[j] = 200;
            j += 1;
        }
        System.out.println(Arrays.toString(ai)); 

        // 番外編 もちろん. 繰り返し処理を使わない方法もあるが、効率が悪い
        ai[0] = 300;
        ai[1] = 300;
        ai[2] = 300;
        ai[3] = 300;
        ai[4] = 300;
        ai[5] = 300;
        ai[6] = 300;
        ai[7] = 300;
        ai[8] = 300;
        ai[9] = 300;
        System.out.println(Arrays.toString(ai)); 
    }
}

メソッドを作る

ポイント

  • メソッド(関数)とは、処理をまとめたもの。
  • 複数箇所で同じ処理をする場合など、その処理を1つのメソッドで定義する。
  • メソッドは「クラスメソッド」と「インスタンスメソッド」の2つがある。まずはクラスメソッドから取り上げる。
    • アクセス修飾子:public, privateなど
    • static:必須
    • 戻り値:メソッドの呼び出し元に返す値の型(何も返さないときはvoid)
    • 仮引数:メソッドに渡す値(何も渡さないときは省略)

クラスメソッドの宣言

アクセス修飾子 static 戻り値 メソッド名(仮引数) {
  メソッドの処理;
   :
}

プログラム例

Sample11.java
import java.util.Arrays;  // 配列の中身を表示するために必要
public class Sample11 {
    public static void main(String[] args){
        int[] ai = new int[5];

        // メソッドを呼び出すときは値(実引数)を渡す
        // 下の場合、実引数は「ai」と「0」です。
        setArray(ai, 0);
        System.out.println(Arrays.toString(ai)); // 結果:[0, 0, 0, 0, 0]

        setArray(ai, 100);
        System.out.println(Arrays.toString(ai)); // 結果:[100, 100, 100, 100, 100]
    }

    // 指定した値を配列に設定するためのメソッド
    //    引数(仮引数)     int[] array  値を設定する配列
    //                    int   val    値
    //    戻り値(復帰値)   なし
    public static void setArray(int[] array, int val){
        for(int i = 0; i < array.length; i++){
            array[i] = val;
        }
    }
}

リファレンス

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ArrayListとLinkedListの違い

先日ArrayListとLinkedListの違いわかるかと聞かれて、答えることができなかったので備忘録として記事します。

ArrayListとは

ArrayListは、内部的には配列を利用したリスト構造です。標準的な配列と異なる点は、サイズを後からでも変更できる点です。その性質上、インデックス値による値の読み書きは高速ですが、要素の挿入/削除は、配列サイズが大きくなるほど、また、操作位置が先頭に近くなるほど遅くなります。

・メリット
要素がそれぞれ順序番号を持っており、全てメモリ上でインデックス化されているため、特定の要素へすぐにアクセスすることが出来ます。

・デメリット
末尾意外の要素を足したり引いたりすると、それ以降の要素全ての順序番号を繰り上げたり繰り下げたりするための再配置処理が行われ、
その処理により ArrayList 内の要素には全て 0 から 全要素数から 1 引いた数までの全ての順序番号が付けられた要素がキレイに並び続けるのですが、処理が行われる分時間がかかってしまいます。
そしてその処理数は要素数に比例して多くなります。

メソッド 概要
add([int index,] E e) 指定位置indexに要素eを挿入(index省略で末尾に挿入)
clear() リストからすべての要素を削除
contains(Object e) リストに要素oが含まれているかを判定
get(int index) be
indexOf(Object e) 要素oが登場する最初のインデックス値を取得
isEmpty() リストが空か判定
remove(int index|Object o) 指定の要素を削除
set(int index, E e) index番目の要素を設定int size()
int size() リストに含まれる要素の数を取得

LinkedListとは

LinkedListは、要素同士を前後双方向のリンクで参照するリンクリストを表します。その性質上、要素の挿入/削除はリンクの付け替えで済むため、ArrayListに較べても高速です。反面、インデックス値によるランダムなアクセスは苦手であるという性質を持ちます。このような理由から、挿入/削除操作が多い状況ではLinkedListを、それ以外の場合はArrayListを使う、という使い分けになるでしょう。
LinkedListクラスで利用できるメソッドは、ArrayListと同じですので、そちらも合わせて参照してください。以下は、LinkedListで要素をセットし、その内容を順に読み込む例です。

・メリット
要素を足したり引いたりする際は、リンク情報を書き換えれば終わりなので、再配置処理が行われない分 ArrayList よりも高速です。

・デメリット
それぞれの要素は順序番号を保持していないため、特定の要素を取り出す際は、先頭もしくは末尾から一つずつ順序を数えていく必要があるため、順序番号があらかじめ保持されている ArrayList に比べると、それだけ多くの時間がかかります。

結論

ArrayListは要素に対してランダムなアクセスを必要とし、配列内の要素に対して挿入/削除の操作があまり必要ない場合に利用。
LinkedListは末尾の要素以外に追加/削除処理を頻繁に必要とし、特定の要素に対するアクセスが必要としない場合に利用。

参照

LinkedList と ArrayList の使い分け方
ArrayListクラス

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Java 初めての例外処理(備忘録)

Java練習

Javaで開発をすることになり現在Javaを勉強中
スッキリわかるJava入門 第2版 スッキリわかるシリーズを使ってJavaの勉強。

2章2-3のアプリをアレンジしてみた。

2章2-3のアプリをアレンジ

dokojavaを使用してブラウザでJavaを実行

Main.java
import java.util.Scanner;
import java.util.Random;

public class Main{
  public static void main(String[] args) {
    System.out.println("ようこそ占いの館へ\nあなたの名前を入力してください");
    String name = new Scanner(System.in).nextLine();
    System.out.println("あなたの年齢を入力してください。");
    String ageString = new Scanner(System.in).nextLine();
    if (isNumber(ageString)){
      int age = Integer.parseInt(ageString);
      int fortune = new Random().nextInt(4) + 1;
      System.out.println("占いの結果が出ました。");
      System.out.println( age + "歳の" + name + "さん、あなたの運勢は" + fortune + "です");
      System.out.println("1:大吉、2:中吉、3:吉、4:凶");
    } else {
      System.out.println("年齢が数字ではありません");
    }
  }
  static boolean isNumber(String num) {
    try {
      Integer.parseInt(num);
      return true;
    } catch (NumberFormatException e) {
      return false;
    }
  }
}
Main.java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        System.out.println("ようこそ\n数字を入力してください");
        String s = new Scanner(System.in).nextLine();
        try {
            //例外が発生する可能性のある処理
            int i = Integer.parseInt(s);
            System.out.println(i);
        } catch (NumberFormatException e) {
            //例外が発生した場合の処理(例外が発生しなければ行われない処理)
            System.out.println("ちゃんと数字を入力してください!");
        }
    }
}

例外処理とは?

プログラムの実行中に,プログラムが予想していなかった事態が起きることがあります

ざっくり言うと例外処理とは,上で述べたような異常事態(例えば想定したデータ型と違う)の発生を通知するための仕組みです.

異常事態の発生を検知したメソッド(例えばparseInt)は例外を「投げ」ます。

これにより異常事態が発生したことを知らせます。

Javaの用語では「投げる」ことを「スロー(throw)する」と言います。

異常事態が発生したメソッドを呼び出した側のメソッドでは,投げられた例外を「捕える」ことができます.捕まえれば,適切な処理を行うことができます(同じく捕まえることを「キャッチ(catch)する」と言います)

参考にした記事(いつもありがとうございます。)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む