20200703のJavaに関する記事は17件です。

【Java】クラスの継承とは?

クラスの継承とは

継承とは、親クラス(スーパークラス)を基に子クラス(サブクラス)を作成することで共通処理を引き継ぎながらも、子クラス独自の処理を記述するための機能のことです。継承を使えるようになると、何度も同じようなプログラムを書く必要がなく、作業の効率化、ソースコード全体を見やすくさせることができます。

Javaクラスの継承方法

継承する場合にはクラス宣言のあとに「extends」を付け継承元とする親クラス名を指定します。ただし、Javaの継承元とするクラスは1つだけです。2つのクラスを同時に継承することはできないようになっています(多重継承の禁止)。

class クラス名 extends 元となるクラス名 {
  親クラスとの「差分」メンバ
}

継承したクラスのメソッドやコンストラクタを使用する場合には、「super」を使用してアクセス・参照します。

class クラス名 extends 元となるクラス名(引数) {
  // 親クラスのコンストラクタの呼び出し
  super(引数);
  // 親インスタンス部分のメソッドを呼び出す
  super.メソッド名(引数);
}

メソッドのオーバーライド

オーバーライドとは親クラスで定義したメソッドの内容を上書きすることです。親クラスで定義されているメソッドの中身を、少し変えて使いたい場合に使用されます。
オーバーライドの条件は、メソッド名、戻り値、引数が同じであることです。

  【親クラス】
    public void output() {
      System.out.println("継承");
    }
  【子クラス】
    public void output() {
      System.out.println("オーバーライド");
    }

親クラス(スーパークラス)を再利用しつつも、変えたいメソッドは自由に変えられるので、便利なオーバーライドですが、使用する上で守らなければならない決まり事がいくつかあります。まず、親クラス(スーパークラス)側のメソッドにfinal修飾子が付与されている場合は、子クラス(サブクラス)でそのメソッドのオーバーライドはできません。また、スーパークラス内のprivate修飾子の付いた変数やメソッドはサブクラスから利用できないことにも気を付ける必要があります。

オーバーロードとの違い

オーバーライドと似たような用語でオーバーロードがあります。よく間違われるので、簡単に説明しておきます。
オーバーロードとはクラス内に「同じ名称のメソッド」を複数宣言することです。
オーバーロードの条件は、➀メソッド名が同じである事 ➁引数の型や数、並び順が異なることです。

  public void output() {}
  public void output(String str) {}
  public void output(String str, int i) {}
  public void output(int i, String str) {}

まとめ

クラスの継承を使うことで、子クラスでは親クラスのメンバ変数やメンバメソッドを改めて記述する必要がなくなります。そうすることで、コードも読みやすくなり後々の修正やメンテナンスがしやすくなります。

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

Androidスマホ・タブレットは何でもできる!Termuxで動かすアレコレまとめ

「使ってないAndroidスマホ,タブレットがある」
「これサーバーにできないかな?」

その夢,かなえられます。

少々めんどくさい作業もありますが,やっていけば必ずできます。

どうやって動かすか

Androidには「Termux」というアプリがあります。
これを使うと,Linuxを動かすことができます。
パッケージもAPTで管理されていて,豊富です。

https://play.google.com/store/apps/details?id=com.termux&hl=ja

また,GBoardなどのキーボードですと不便を感じるかもしれません。
「Hacker's Keyboard」がおすすめです。

https://play.google.com/store/apps/details?id=org.pocketworkstation.pckeyboard&hl=ja

下ごしらえ

Linuxに触れたことのある方は慣れていると思います。

まず,Termuxが端末内のファイルにアクセスできるようにするには権限を与える必要があります。

$ termux-setup-storage

これを実行すると,Android 8以降では権限ダイアログが出ますので許可してください。

Termuxではaptのエイリアスとして「pkg」コマンドが用意されています。

コマンド 説明
pkg update apt updateを実行後apt upgradeを行う
pkg install <package...> apt install <package...>
pkg remove apt remove <package...>

他にもコマンドがあります。pkgだけ実行するとヘルプを見れます。

さっそく,パッケージを最新にします。

$ pkg update

アップデートが完了したら,下ごしらえはおしまいです。

Termuxの基本

ディレクトリ

Termuxの中では,ルートディレクトリは /data/data/com.termux/files/usr になっています。
これは,$PREFIXで表せます。
以下に例を挙げます。

本来のディレクトリパス Termuxでのパス
/etc $PREFIX/etc
/usr/share $PREFIX/share
/bin $PREFIX/bin

エディタ

nanoが標準でついています。

$ nano filename

で起動できます。

よく使うキーボード操作を挙げておきます。

キーボード入力 意味
Ctrl + X 終了
Ctrl + O 保存

使用できるポートの制限

Termuxは 1024~65535 の範囲で使用できます。
80や443などは使えませんので,インターネットに公開する場合はポート変換が必要になる場合があります。

あれこれ

PCからシェルに入る (telnet)

本来はTelnetはネットに公開しちゃいけないものです。ローカルで使うだけにしておきましょう。

$ pkg install busybox

busyboxをインストールしたら

$ busybox telnetd -p 5888

とします。-p 数字はポート番号です。
TeraTermなどで,アクセス可能です。

HTTPサーバーを建てる

パッケージのインストール

Termuxにも apache2 (httpd),nginxパッケージがありますので,インストールできます。
PHPも使いたい場合は,apache2の場合は phpphp-apache が必要です。
nginxの場合は phpphp-fpm が必要です。

【apache2の場合】

$ pkg install apache2 php php-apache

【nginxの場合】

$ pkg install nginx php php-fpm

設定を変える (apache2)

設定ファイルは $PREFIX/etc/apache2/httpd.conf です。

PHPを使う場合,設定の変更が必要です。

$ nano $PREFIX/etc/apache2/httpd.conf

でエディタを起動します。

まず,先頭に ServerRoot "..."という項目があると思います。
その次の行に

HostnameLookups On

を記述します。これは,ログにホスト名を表示させるようにするための設定です。

次に,

LoadModule mpm_worker_module xxxxxxxx

と書いてある行があるはずです。それはコメントアウトします。
代わりに,その行の一つ上にある

#LoadModule mpm_prefork_module xxxxxxx

のコメントアウトを解除します (#を外します)

次に,どんどん下へ行くと DocumentRoot "..."の行が見えてくると思います。
その周辺にある

Options Indexes FollowSymLinks

の行に,ExecCGI を書き足します。書き足すと

Options Indexes FollowSymLinks ExecCGI

となります。
その下の

DirectoryIndex indexうんたら

DirectoryIndex index.php index.html index.htm

に変えます。

最後に,ファイルの一番最後の行に

LoadModule php7_module libexec/apache2/libphp7.so
AddHandler php7-script .php

を追加しておしまいです。
Ctrl+Oで保存するのを忘れずに!

設定を変える (nginx)

httpdより,少し厄介かもしれないですね。

設定ファイルは $PREFIX/etc/nginx/nginx.conf です。

$ nano $PREFIX/etc/apache2/httpd.conf

でエディタを起動します。

まず,

location / {
 ...
}

という行があると思います。その中の

index index.html index.htm;

index index.php index.html index.htm;

にします。

次に

# pass the PHP script ほにゃららら
#
location ~ \.php$ {
 ...
}

という行があると思います。
コメントアウトされているはずですので,その部分すべて外します。

その後,その部分は以下のように置き換えます

location ~ \.php$ {
 root (任意のディレクトリ);
 fastcgi_pass unix:/data/data/com.termux/files/usr/var/run/php-fpm.sock;
 fastcgi_index index.php;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 include fastcgi_params;
}

Ctrl+Xで保存して,エディタを終了します。

次にPHPの設定をします。

$ nano $PREFIX/etc/php-fpm.d/www.conf

でエディタを起動します。

スクロールしていくと, listen = ....という行があります。
そこを

listen = /data/data/com.termux/files/usr/var/run/php-fpm.sock

に書き換えます。
Ctrl+Oで保存して,おしまいです。

httpdを起動

httpdを起動させるには

$ httpd

だけでいいです。何かログを吐きますが特に気にする必要はありません。
止める時は

$ httpd -k stop

または


$ killall httpd

です。

nginxを起動

nginxは

$ nginx

とするだけです。

なお,PHPを使う場合は nginx を実行する前に

$ php-fpm

を実行する必要があります。

止める時は

$ killall nginx

です。

DiscordBot (Python)を動かす

PythonでBotを作ったのであれば,それもTermuxで動かせます。

Pythonは3.8をインストールできます。

$ pkg install python make automake autoconf clang build-essential git

なお,このインストール作業には約500MBを消費します。ストレージに2GB以上の空きがあるか確かめてください。

その後,

$ pip install wheel requests
$ pip install -U "discord.py[voice]"

を実行します。
途中PyNaClのビルドが行われます。スマートフォン・タブレットの性能によっては,完了するまで2~5分かかる場合があります。時間に余裕をもって行ってください。

さきほどgitもインストールしたので,リポジトリからプログラムを下ろしたりできます。

GitHubからプログラムを下ろす

Gitの使い方に慣れている人は説明はいらないと思います。
ということで,事前に使い方を知っているものとしてコマンドを記載します。

$ git config --global user.name "Your Name"
$ git config --global user.email "youremail@example.com"
$ git config --global crediential.helper "cache"
$ git clone https://github.com/xxxx/xxxx.git

botを起動

起動するプログラムがあるディレクトリにいる状態で

$ python filename.py

とします。

Minecraft (PC版) のサーバーを建てる

なんと,TermuxではJavaを動かせます。

さっそくインストールしましょう。
ここでは有志の方のものを使います。なお,OpenJDK 8となります。

$ pkg install wget && wget https://raw.githubusercontent.com/MasterDevX/java/master/installjava && bash installjava

ダウンロードが終わるまで時間がかかるかもしれません。気長に待ちます。
その後,java と打ってヘルプが出てきたら完了です。

server.jar をダウンロードする

サーバーは https://mcversions.net/ からダウンロードできます。
使用法については割愛します。
建てたいバージョンにあったサーバープログラムをダウンロードします。

バージョン URL
1.15.1 https://launcher.mojang.com/v1/objects/4d1826eebac84847c71a77f9349cc22afd0cf0a1/server.jar
1.15.2 https://launcher.mojang.com/v1/objects/bb2b6b1aefcd70dfd1892149ac3a215f6c636b07/server.jar
1.16 https://launcher.mojang.com/v1/objects/a0d03225615ba897619220e256a266cb33a44b6b/server.jar
1.16.1 https://launcher.mojang.com/v1/objects/a412fd69db1f81db3f511c1463fd304675244077/server.jar

上のURLをコピーして,

$ cd ~
$ mkdir mcserver
$ cd mcserver
$ wget コピーしたURL

を実行します。
貼り付けは,画面のどこかを長押しして出る「PASTE」を押すとできます。
ダウンロードできたら

$ echo "eula=true" > eula.txt
$ java -jar server.jar

とします。
いろいろログが出て,ワールドの生成が行われます。
あまりにも性能が低いと,クラッシュする場合がありますので注意してください。

また,Android 8以降ではこのままだと

$ java -jar server.jar
Bad system call
$

となってしまいますので,このコマンドを実行する前に

$ proot -0

を実行してください。

おわりに

いかがでしたか?結構できること,ありましたね。
ネットにはもっと詳しいことが書いてありますので,ぜひ挑戦してみてください。
それではよいTermuxライフを!

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

JavaでMapのバリューを1行でインクリメントする方法

書き方(Java8以降)

書き方
map.merge(key, 1, Integer::sum);

動かしてみる

例示
jshell> Map<String, Integer> map = new HashMap<>();
map ==> {}

jshell> map.put("apple", 0);
$2 ==> null

jshell> map.get("apple");
$3 ==> 0

jshell> map.merge("apple", 1, Integer::sum);
$4 ==> 1

jshell> map.get("apple");
$5 ==> 1

jshell> map.merge("apple", 1, Integer::sum);
$6 ==> 2

jshell> map.get("apple");
$7 ==> 2

なんで?

IntegerのsumメソッドとMapのmergeメソッドを調べましょう

Integer.sum

2つの引数を単純に加算しているだけです。

sum
public static int sum(int a,
int b)
+演算子のように、2つの整数を加算します。
パラメータ:
a - 第1オペランド
b - 第2オペランド
戻り値:
aとbの合計
導入されたバージョン:
1.8

Oracleのドキュメント

Map.merge

default V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)
指定されたキーがまだ値と関連付けられていないかnullと関連付けられている場合、指定されたnull以外の値に関連付けます。それ以外の場合は、指定された再マッピング関数の結果で関連する値を置換し、結果がnullの場合は削除します。

Oracleのドキュメント

つまり、第2引数のvalueはnullだった場合のデフォルト値で、nullでない場合は第3引数の関数の結果が設定されます。

第3引数の関数も引数を2つとります。
第3引数の関数の1つ目の引数はkeyに対してのvalueです。
第3引数の関数の2つ目の引数は第2引数と同じvalueがnullだった場合の値です。

[Java] Map#mergeが分かりづらい。

変数に名前をつけるとこんな感じでしょうか

map.merge(key, defaultValue, (value, defaultValue) -> function());

つまり?

map.merge(key, 1, Integer::sum)はデフォルト値をstep(1回の処理で加算される数)のように扱い、valueとデフォルト値をIntegerのsumをメソッド参照で合算しています。

参考

https://stackoverflow.com/questions/81346/most-efficient-way-to-increment-a-map-value-in-java

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

SpringBoot入門ガイドやってみた【Consuming a RESTful Web Service編】

目的

Spring Quickstart Guideを取り組み終えた方、SpringBootを学び始めた方、復習をしたい方に向けて、

公式が人気ガイドだからやってみて!と勧めてくれている、Consuming a RESTful Web Serviceを実際に取り組み学んだことを共有します。

開発環境
OS: macOS Mojave バージョン10.14.6
テキストエディタ: Visual Studio Code(以下VSCode)
Java: 11.0.2

QuickstartGuideのおさらいはこちらから
Building a RESTful Web Service編のおさらいはこちらから

1.SpringBoot projectを始めよう!

まずは、spring initializrにアクセスします。

1.ADD DEPENDENCIESボタンをクリックして、Spring Webを追加。
2.Artifact, Nameは、consumingrestに変更。
3.Javaを11に変更。

そしてGENERATEボタンをクリックしてZipファイルをダウンロードします。

スクリーンショット 2020-07-02 14.08.50.png

ダウンロードしたZipファイルを展開したら準備完了です。

2.コードを追加しよう!

先ほどのフォルダをVSCodeで開きます。
拡張機能のJava Extension Packのインストールの推奨します。と言われるのでインストールしておきましょう。

スクリーンショット 2020-06-30 10.08.25.png

Quote.javaを作成しよう!

src/main/java/com/example/consumingrest/にQuote.javaファイルを作成します。

スクリーンショット 2020-07-02 14.35.29.png

Quote.javaファイル内にコードを追加していきます。

Quote.java
package com.example.consumingrest;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class Quote {

  private String type;
  private Value value;

  public Quote() {
  }

  public String getType() {
    return type;
  }
  public void setType(String type) {
    this.type = type;
  }

  public Value getValue() {
    return value;
  }
  public void setValue(Value value) {
    this.value = value;
  }

  @Override
  public String toString() {
    return "Quote{" +
        "type='" + type + '\'' +
        ", value=" + value +
        '}';
  }
}

Quote.javaファイルに追加したコードを深掘りしていきます。

@JsonIgnoreProperties

JavaのオブジェクトをJSONに変換したり、JSONの文字列を受け取ってJavaオブジェクトに変換する際に、
複数のフィールドを変換対象外としてくれるアノテーションです。

ignoreUnknown = trueと設定することで、未定義の(余計な)プロパティを変換しようとした時に例外が出るのを防いで、あくまでtypeとvalueだけを変換してくれるようになります。

②変数の宣言

private String type;
private Value value;

string型のtypeとValue型のvalue変数を宣言しています。

アクセス修飾子はprivateですので、同一クラス内からしかアクセス出来ません

③コンストラクタ、ゲッター/セッターメソッドの定義

// コンストラクタ
public Quote() {
}

// typeのゲッター/セッターメソッド
public String getType() {
  return type;
}
public void setType(String type) {
  this.type = type;
}

// valueのゲッター/セッターメソッド
public Value getValue() {
  return value;
}
public void setValue(Value value) {
  this.value = value;
}

引数なしのコンストラクタを定義しています。

type、valueの値を取得するゲッターメソッド、値をセットするセッターメソッドを定義しています。

@Override

@Override
public String toString() {
  return "Quote{" +
      "type='" + type + '\'' +
      ", value=" + value +
      '}';
}

toStringメソッドは、java.lang.Objectクラスで定義されている文字列表現を返すメソッドです。
@Overrideアノテーションは、Objectクラスで定義されているtoStringメソッドをこのクラスでオーバーライドしています。と明示するためのアノテーションです。

正しくオーバーライドされていなければエラーになります。
よって、toStrign()のようにタイプミスをしてしまっていると、コンパイル時にエラーが出て教えてくれます。

今回は、typeとvalueを分かりやすいように表示するための文字列を返すようにオーバーライドしています。

Quote.javaはこれで完成です。

Value.javaを作成しよう!

src/main/java/com/example/consumingrest/にValue.javaファイルを作成します。

スクリーンショット 2020-07-02 16.55.28.png

Value.javaファイル内にコードを追加していきます。

Value.java
package com.example.consumingrest;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class Value {

  private Long id;
  private String quote;

  public Value() {
  }

  public Long getId() {
    return this.id;
  }
  public String getQuote() {
    return this.quote;
  }

  public void setId(Long id) {
    this.id = id;
  }
  public void setQuote(String quote) {
    this.quote = quote;
  }

  @Override
  public String toString() {
    return "Value{" +
        "id=" + id +
        ", quote='" + quote + '\'' +
        '}';
  }
}

Value.javaはQuote.javaとほぼ同じですね。

ConsumingrestApplication.javaを編集しよう!

デフォルトの状態は以下のようになっていると思います。

ConsumingrestApplication.java
package com.example.consumingrest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConsumingrestApplication {

  public static void main(String[] args) {
    SpringApplication.run(ConsumingrestApplication.class, args);
  }

}

公式を参考にしつつコードを追加します。

ConsumingrestApplication.java
package com.example.consumingrest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

// 追加したコード
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class ConsumingrestApplication {

  // 追加したコード
  private static final Logger log = LoggerFactory.getLogger(ConsumingrestApplication.class);

  public static void main(String[] args) {
    SpringApplication.run(ConsumingrestApplication.class, args);
  }

  // 追加したコード
  @Bean
  public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder.build();
  }

  // 追加したコード
  @Bean 
  public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
    return args -> {
      Quote quote = restTemplate.getForObject(
        "https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
      log.info(quote.toString());
  }

}

ConsumingrestApplication.javaファイルに追加したコードを深掘りしていきます。

①ログ出力のためのlog

private static final Logger log = LoggerFactory.getLogger(ConsumingrestApplication.class);

ターミナルでログを表示するためにLogger、LoggerFactoryを用いています。
LoggerFactory.getLogger()の引数にクラスを指定してログを取得することが出来ます。

②RestTemplate

// 追加したコード
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
  return builder.build();
}

RestTemplateは、REST API(Web API)を呼び出すためのメソッドを提供するHTTPクライアントクラスです。
今回は、URLにGETリクエストを送り、送信先のレスポンスのコンテンツをQuote.classに格納するために用います。

@Beanというアノテーション、RestTemplateBuilderを用いて、DIコンテナに登録しています。
Bean登録するには、Springの色々な設定を Java コード上で行えるようにするためのアノテーションである
@Configurationを付与しなければいけませんが、@SpringBootApplicationというアノテーションの中に含まれています。

③CommandLineRunner

// 追加したコード
@Bean 
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
  return args -> {
    Quote quote = restTemplate.getForObject(
      "https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
    log.info(quote.toString());
}

CommandLineRunnerはrunというメソッドをもつ関数型インターフェースです。
よってここでは、runメソッドのオーバーライドをしています。

SpringBootがアプリ実行後に呼び出してくれます。

処理の流れとしては、
Quote型のquote変数にrestTemplate.getForObject()の結果を代入しています。
第一引数にGETリクエストを送るURLを指定、第二引数に送信先のレスポンスのコンテンツを格納するクラスを指定しています。

その後、①で定義したlogのinfoメソッドを呼び出し、その中で更にQuoteクラスのtoStringメソッドを呼び出しています。

3.実行してみよう!

アプリケーション実行の準備が出来たので確認しましょう。

ターミナルで以下のコマンドを入力してEnterしてください。

ターミナル
$ ./mvnw spring-boot:run

しばらくすると、ターミナルに以下の文字が出てきます。

ターミナル
Quote{type='success', value=Value{id=12, quote='@springboot with @springframework is pure productivity! Who said in #java one has to write double the code than in other langs? #newFavLib'}}

このidとquoteはランダムに表記されるので、アプリケーションを停止して再度ターミナルで実行コマンドを入力すると。

ターミナル
Quote{type='success', value=Value{id=4, quote='Previous to Spring Boot, I remember XML hell, confusing set up, and many hours of frustration.'}}

先程とは違うidとquoteになっています。

参考サイト

RestTemplate
CommandLineRunner
jacksonでデシリアライズする際に未知のプロパティを無視する
DIについて理解する
SpringのDIコンテナの動作イメージ(雰囲気)を掴もう
Spring Bootで簡単なコマンドラインアプリケーションを作成してみる

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

図鑑 データ構造 アルゴリズム Java

図鑑 データ構造 アルゴリズム Java
https://www.amazon.co.jp/dp/B089G7V8HH
図鑑 データ構造 アルゴリズム Java Small.jpg

データ構造とアルゴリズムJavaの実践、トピック自体は複雑ですが、読みやすく理解しやすいように設計されています。アルゴリズムは、ソフトウェアプログラムがデータ構造を操作するために使用する手順です。明確で単純なサンプルプログラムに加えて、プログラムは、データ構造がどのように見え、どのように動作するかをグラフィック形式で示します。基本的なつのデータ構造をすべてイラストで解説,誌面がフルカラーなので、図の「動き」がわかりやすい,あなたはそれを簡単に、速く、うまく学びます。

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

(学習メモ)Java2級対策:問1まとめ

Java
自己学習用メモ

問1要点整理

   

Oya 
- 継承 ー> Ko(Oyaのサブクラス) 
- 継承 ー> Mago(Oyaのサブクラス)

this はスーパークラスでなくても使用OK
java.io.FileOutpuStreamクラスは
java.lang.Objectクラスのサブクラス
Javaは「多重継承」NG!!
サブクラスはスーパークラスの属性・操作を引き継ぐことができる
スーパークラスの参照変数には、
 サブクラスのオブジェクトを代入OK!

--------- TBE -------------

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

JavaはExcelドキュメントプロパティを設定します

Excelドキュメントプロパティは説明的な情報であり、作成者、タイトル、件名、キーワード、カテゴリなどのアイテムが含まれます。Excelドキュメントのプロパティを設定することで、ユーザーがExcelドキュメントをより便利かつ迅速に管理できるようになります。この記事では、Free Spire.XLS for Javaを使用して、Excel文書に組み込みのドキュメントプロパティとカスタムドキュメントプロパティを設定する方法を紹介します。

環境構成:
方法1: Free Spire.XLS for Javaパッケージをダウンロードして解凍し、libフォルダーのSpire.Xls.jarパッケージを依存関係としてJavaアプリケーションにインポートします。

方法2: Mavenリポジトリから直接JARパッケージをインストールすることもできますpom.xmlファイルを構成するコードは次のとおりです。

<repositories>
        <repository>
            <id>com.e-iceblue</id>
            <name>e-iceblue</name>
            <url>http://repo.e-iceblue.com/nexus/content/groups/public/</url>
        </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.xls.free</artifactId>
        <version>2.2.0</version>
    </dependency>
</dependencies>

組み込みのドキュメントプロパティを設定します:

import com.spire.xls.ExcelVersion;
import com.spire.xls.Workbook;

public class BuiltinProperties {
    public static void main(String[] args){
        //Excelドキュメントを読み込む
        Workbook workbook = new Workbook();
        workbook.loadFromFile("test.xlsx");

        //ドキュメントのタイトル、件名、作成者、およびその他の組み込みドキュメント属性を設定する
        workbook.getDocumentProperties().setTitle("ドキュメントプロパティを設定する");
        workbook.getDocumentProperties().setSubject("注文書");
        workbook.getDocumentProperties().setAuthor("AAA");
        workbook.getDocumentProperties().setManager("BBB");
        workbook.getDocumentProperties().setCompany("C社");
        workbook.getDocumentProperties().setCategory("支出");
        workbook.getDocumentProperties().setKeywords("Excelドキュメントのプロパティ");

        //結果ファイルを保存
        workbook.saveToFile("BuiltinDocumentProperties.xlsx", ExcelVersion.Version2013);
    }
}

in.jpg

カスタムドキュメントプロパティを設定します:

import com.spire.xls.ExcelVersion;
import com.spire.xls.Workbook;

import java.util.Date;

public class CustomProperties {
    public static void main(String[] args){
        //Excelドキュメントを読み込む
        Workbook workbook = new Workbook();
        workbook.loadFromFile("Input.xlsx");

        //ドキュメントにカスタムドキュメントプロパティを追加する
        workbook.getCustomDocumentProperties().add("_MarkAsFinal", true);
        workbook.getCustomDocumentProperties().add("編集する", "AAA");
        workbook.getCustomDocumentProperties().add("連絡先番号", 81705109);
        workbook.getCustomDocumentProperties().add("日付", new Date());

        //結果ファイルを保存
        workbook.saveToFile("CustomDocumentProperties.xlsx", ExcelVersion.Version2013);
    }
}

cu.png

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

JavaはExcelドキュメントプロパティを設定します

Excelドキュメントプロパティは説明的な情報であり、作成者、タイトル、件名、キーワード、カテゴリなどのアイテムが含まれます。Excelドキュメントのプロパティを設定することで、ユーザーがExcelドキュメントをより便利かつ迅速に管理できるようになります。この記事では、Free Spire.XLS for Javaを使用して、Excel文書に組み込みのドキュメントプロパティとカスタムドキュメントプロパティを設定する方法を紹介します。

環境構成:
方法1: Free Spire.XLS for Javaパッケージをダウンロードして解凍し、libフォルダーのSpire.Xls.jarパッケージを依存関係としてJavaアプリケーションにインポートします。

方法2: Mavenリポジトリから直接JARパッケージをインストールすることもできますpom.xmlファイルを構成するコードは次のとおりです。

<repositories>
        <repository>
            <id>com.e-iceblue</id>
            <name>e-iceblue</name>
            <url>http://repo.e-iceblue.com/nexus/content/groups/public/</url>
        </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.xls.free</artifactId>
        <version>2.2.0</version>
    </dependency>
</dependencies>

組み込みのドキュメントプロパティを設定します:

import com.spire.xls.ExcelVersion;
import com.spire.xls.Workbook;

public class BuiltinProperties {
    public static void main(String[] args){
        //Excelドキュメントを読み込む
        Workbook workbook = new Workbook();
        workbook.loadFromFile("test.xlsx");

        //ドキュメントのタイトル、件名、作成者、およびその他の組み込みドキュメント属性を設定する
        workbook.getDocumentProperties().setTitle("ドキュメントプロパティを設定する");
        workbook.getDocumentProperties().setSubject("注文書");
        workbook.getDocumentProperties().setAuthor("AAA");
        workbook.getDocumentProperties().setManager("BBB");
        workbook.getDocumentProperties().setCompany("C社");
        workbook.getDocumentProperties().setCategory("支出");
        workbook.getDocumentProperties().setKeywords("Excelドキュメントのプロパティ");

        //結果ファイルを保存
        workbook.saveToFile("BuiltinDocumentProperties.xlsx", ExcelVersion.Version2013);
    }
}

in.jpg

カスタムドキュメントプロパティを設定します:

import com.spire.xls.ExcelVersion;
import com.spire.xls.Workbook;

import java.util.Date;

public class CustomProperties {
    public static void main(String[] args){
        //Excelドキュメントを読み込む
        Workbook workbook = new Workbook();
        workbook.loadFromFile("Input.xlsx");

        //ドキュメントにカスタムドキュメントプロパティを追加する
        workbook.getCustomDocumentProperties().add("_MarkAsFinal", true);
        workbook.getCustomDocumentProperties().add("編集する", "AAA");
        workbook.getCustomDocumentProperties().add("連絡先番号", 81705109);
        workbook.getCustomDocumentProperties().add("日付", new Date());

        //結果ファイルを保存
        workbook.saveToFile("CustomDocumentProperties.xlsx", ExcelVersion.Version2013);
    }
}

cu.png

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

(学習メモ)Java2級対策:問4要点

Java
自己学習用メモ

問4 要点整理

例外処理について

  • finallyブロック、catchブロック
  • それぞれどちらかがあれば片方は省略できる。
  • finallyブロック内でtry~catchブロックを記述することはできない。
  • 複数のfinallyブロックを記述することはできない。

--------- TBE -------------

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

[Processing�×Java] クラスを具体化してオブジェクトを作り、オブジェクトの特性を活かしつつそれを変数のように扱う

この記事はプログラムの構造をProcessingを通じて理解していくための記事です。
今回はオブジェクト指向プログラミングについて書いていきます。

目次
0.データ型
1.オブジェクト指向プログラミング

0.データ型

0-0. データって何・・?

データは情報。
体重、身長、目の色、車のナンバー、日照時間、降水量、住所、画像、などなど。。
Point :データはコンピューターのメモリでは、ビット(0と1)の集合で表されます。
Point :データには種類( データ型 )があり、種類別に保存されます。

0-1. データ型について

データ型(データの種類)には、基本データ型複合データ型があります。

[基本データ型]

基本データ型は、"1つのデータ要素のみ"を格納します。

名前 データ要素 サイズ(ビット) 値の範囲
boolean 真偽値 1 trueまたはfalse
byte バイト 8 -128から127
char 1文字の英数字、記号 16 0から65535
int 整数 32 -2,147,483,648から2,147,483,647
float 浮動小数点数 32 3.40282347E + 38から-3.40282347E + 38
color 32 16,777,216色

[複合データ型]

複合データ型は、"複数のデータや、関数(メソッド)"を含んでいます。
※複合データ型はクラスとも呼ばれます。

名前 データ要素 メソッド
String 文字列 length(),charAt(),equals(),indexOf(),toLowerCase(),toUpperCase()...
PImage 画像 loadPixels(),updatePixels(),resize(),get(),set(),mask(),filter(),blend(),save()...
PFont フォント list()
PShape 図形 beginShape(),endShape(),translate(),rotate(),scale()...
PVector 座標 set(),mag(),magsq(),add(),sub(),mult(),dist(),normalize(),lerp()...
:

※クラスの名前は大文字からはじまっているので基本データ型と簡単に区別がつきます。

0-2. データ型の使用例

[基本データ型]

データ型 : boolean

boolean.java
//変数の宣言と初期設定
boolean b = false;

size(640, 360);
background(0);
//Build-in変数は、size()で定義されてからでないと使えません。
int middle = width/2;

//線を描いていくループ
for (int i = 0; i <= width; i += 20) {
  //どんなときtrueで、どんなときfalseなのかを決める。
  if (i < middle) {
    b = true;
  } else {
    b = false;
  }
  //もし、trueなら
  if (b == true) {
    stroke(255,0,0);
  }
  //もし、falseなら 
  if (b == false) {
    stroke(0,0,255);
  }
  //線を描いていく
  line(i,0,i,height);
}

b.png

データ型 : char

char.java
//char型の変数letterを作って、初期設定をする。
char letter = 'A';

//char型は文字(アルファベット)の順番を持っているのでそれを利用する。
for(int i = 0;i < 26;i++){
    print(letter);
    letter++;
}
ABCDEFGHIJKLMNOPQRSTUVWXYZ

データ型 : int

int.java
//int型の変数 n を宣言して、初期設定する。
int n = 3;

//5回ループを繰り返す
for(int i = 0;i < 5;i++){
    println(n);
    // n = 2n
    n *= 2;
}
3
6
12
24
48

データ型 : color

color.java
color型の変数blueをcolor()を使って定義する
color blue = color(0,0,255);
background(blue);

color.png

[複合データ型]-----------------------------------------------------------------

データ型 : String

String.java
//クラスStringのオブジェクトs1をつくって、中身を入れる。
String s1 = "breakfast"
//ドット(.)を使ってオブジェクトの持つメソッドにアクセスする。
println(s1.length());
9

s1はインスタンス(クラスを具体化したもの)であり、Stringクラスのオブジェクトであり、変数の種類として見ればインスタンス変数です。

データ型 : PImage

PImage.java
//オブジェクトの宣言
//PImageクラスを具体化してimgというオブジェクトをつくる。
PImage img;

void setup(){
    size(100,100);
    //オブジェクトに中身を入れる。
    img = loadImage("~.png");
}

void draw(){
    //オブジェクトを使う。
    image(img,0,0);
}

1.オブジェクト指向プログラミング

1-0. まずは用語を確認

オブジェクト指向プログラミング
関連のある関数と変数をまとめて定義するプログラムのことです。

クラス
関連するフィールドとメソッドが入ったまとまりのことです。
よくレシピなどに例えられます。

フィールド
クラスの中で定義される変数です。

メソッド
クラスの中で定義される関数です。

オブジェクト
クラスのインスタンス(具体例)のことです。
もとのクラスと同じフィールド名やメソッドを持ちます。
よくレシピを使って作った料理などに例えられます。

インスタンス
あるクラスのオブジェクトのことです。

インスタンス変数
変数の一種です。
オブジェクトが作られたときにできた変数です。

変数
ある名前を持ったデータの要素です。
全ての変数には、値、データ型、スコープがあります。

スコープ
プログラムの中で変数にアクセスできる範囲(ブロック)のことです。
どこで定義するかで使える場所が異なります。

1-1. クラスを使ったプログラミング

◯クラスを使いたい

クラスはただのテンプレートなので、そのままでは使うことができません。
なので、

クラスを具体化してオブジェクトを作り、オブジェクトの特性を活かしつつそれを変数のように扱う。

◯クラスを具体化する

クラスにはフィールドとメソッドが記述されています。
これをプログラムの中で使いたい。
ですがクラスはただのテンプレートで、抽象的な存在。
なので、クラスを具体的な存在(オブジェクト)にしてそれについて操作していきます。

◯クラスを具体化する方法

簡単な例で見てみましょう。
ここでは、クラスStringからオブジェクトs1をつくっています。

String.java
//オブジェクトの宣言
String s1;
//オブジェクトの定義
s1 = "breakfast"
//オブジェクトの使用
println(s1.length());
9

ここで、s1は
インスタンス(クラスのオブジェクト)
であり
オブジェクト(クラスから作られた具体的な存在)
であり、
インスタンス変数(変数の一種)
です。

どこからみるか、基準をどこにするかによって呼び方(外見)は違いますが、中身は一緒です。
いろいろな呼び方があるんだなあってことです。
人間もいろいろな顔を使い分けているでしょう?(表の顔、裏の顔、上司の前での顔などなど)
それと一緒です。

◯オブジェクトの特性を活かしつつそれを変数のように扱う

全てのオブジェクトはクラスが持つフィールドとメソッドを持っています。

・フィールド = クラスの中で定義される変数

・メソッド = クラスの中で定義される関数

オブジェクトを作ったので、やっとクラスの持つフィールドとメソッドを使えそうです。

オブジェクトの持つフィールドやメソッドにアクセスするためにはドット(.)を使ってアクセスします。
オブジェクト自体は、変数と同じように扱います。

String.java
//オブジェクトの定義
String str1 = "goodjob"; 
//オブジェクトが持つメソッドにアクセスする
str1 = str1.toUpperCase();
//オブジェクトを使用する
println(str1);
GOODJOB

変数と同じように使うとは
定義(宣言→初期設定)→使用
のようにして使うということです。

つまりまとめると、ここでのstr1は

□フィールドやメソッドを持っている。(オブジェクトの特性)
□ドットを使って自身のフィールドやメソッドにアクセスする。(使い方)
かつ
□値、データ型、スコープを持つ。(変数の特性)
□定義(宣言、初期設定)してから使う。(使い方)

以上がクラスを使ったプログラムの方法の一部です。

最後に

読んでいただきありがとうございました。
より良い記事にしていくために御意見、ご指摘のほどよろしくお願いいたします。

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

[Processing�×Java] オブジェクト指向プログラミング

この記事はプログラムの構造をProcessingを通じて理解していくための記事です。
今回はオブジェクト指向プログラミングについて書いていきます。

目次
0.データ型
1.オブジェクト指向プログラミング

0.データ型

0-0. データって何・・?

データは情報。
体重、身長、目の色、車のナンバー、日照時間、降水量、住所、画像、などなど。。
Point :データはコンピューターのメモリでは、ビット(0と1)の集合で表されます。
Point :データには種類( データ型 )があり、種類別に保存されます。

0-1. データ型について

データ型(データの種類)には、基本データ型複合データ型があります。

[基本データ型]

基本データ型は、"1つのデータ要素のみ"を格納します。

名前 データ要素 サイズ(ビット) 値の範囲
boolean 真偽値 1 trueまたはfalse
byte バイト 8 -128から127
char 1文字の英数字、記号 16 0から65535
int 整数 32 -2,147,483,648から2,147,483,647
float 浮動小数点数 32 3.40282347E + 38から-3.40282347E + 38
color 32 16,777,216色

[複合データ型]

複合データ型は、"複数のデータや、関数(メソッド)"を含んでいます。
※複合データ型はクラスとも呼ばれます。

名前 データ要素 メソッド
String 文字列 length(),charAt(),equals(),indexOf(),toLowerCase(),toUpperCase()...
PImage 画像 loadPixels(),updatePixels(),resize(),get(),set(),mask(),filter(),blend(),save()...
PFont フォント list()
PShape 図形 beginShape(),endShape(),translate(),rotate(),scale()...
PVector 座標 set(),mag(),magsq(),add(),sub(),mult(),dist(),normalize(),lerp()...
:

※クラスの名前は大文字からはじまっているので基本データ型と簡単に区別がつきます。

0-2. データ型の使用例

[基本データ型]

データ型 : boolean

boolean.java
//変数の宣言と初期設定
boolean b = false;

size(640, 360);
background(0);
//Build-in変数widthは、size()で定義されてからでないと使えません。
int middle = width/2;

//線を描いていくループ
for (int i = 0; i <= width; i += 20) {
  //どんなときtrueで、どんなときfalseなのかを決める。
  if (i < middle) {
    b = true;
  } else {
    b = false;
  }
  //もし、trueなら
  if (b == true) {
    stroke(255,0,0);
  }
  //もし、falseなら 
  if (b == false) {
    stroke(0,0,255);
  }
  //線を描いていく
  line(i,0,i,height);
}

b.png

データ型 : char

char.java
//char型の変数letterを作って、初期設定をする。
char letter = 'A';

//char型は文字(アルファベット)の順番を持っているのでそれを利用する。
for(int i = 0;i < 26;i++){
    print(letter);
    letter++;
}
ABCDEFGHIJKLMNOPQRSTUVWXYZ

データ型 : int

int.java
//int型の変数 n を宣言して、初期設定する。
int n = 3;

//5回ループを繰り返す
for(int i = 0;i < 5;i++){
    println(n);
    // n = 2n
    n *= 2;
}
3
6
12
24
48

データ型 : color

color.java
color型の変数blueをcolor()を使って定義する
color blue = color(0,0,255);
background(blue);

color.png

[複合データ型]-----------------------------------------------------------------

データ型 : String

String.java
//クラスStringのオブジェクトs1をつくって、中身を入れる。
String s1 = "breakfast"
//ドット(.)を使ってオブジェクトの持つメソッドにアクセスする。
println(s1.length());
9

s1はインスタンス(クラスを具体化したもの)であり、Stringクラスのオブジェクトであり、変数の種類として見ればインスタンス変数です。

データ型 : PImage

PImage.java
//オブジェクトの宣言
//PImageクラスを具体化してimgというオブジェクトをつくる。
PImage img;

void setup(){
    size(100,100);
    //オブジェクトに中身を入れる。
    img = loadImage("~.png");
}

void draw(){
    //オブジェクトを使う。
    image(img,0,0);
}

1.オブジェクト指向プログラミング

1-0. まずは用語を確認

オブジェクト指向プログラミング
関連のある関数と変数をまとめて定義するプログラムのことです。

クラス
関連するフィールドとメソッドが入ったまとまりのことです。
よくレシピなどに例えられます。

フィールド
クラスの中で定義される変数です。

メソッド
クラスの中で定義される関数です。

オブジェクト
クラスのインスタンス(具体例)のことです。
もとのクラスと同じフィールド名やメソッドを持ちます。
よくレシピを使って作った料理などに例えられます。

インスタンス
あるクラスのオブジェクトのことです。

インスタンス変数
変数の一種です。
オブジェクトが作られたときにできた変数です。

変数
ある名前を持ったデータの要素です。
全ての変数には、値、データ型、スコープがあります。

スコープ
プログラムの中で変数にアクセスできる範囲(ブロック)のことです。
どこで定義するかで使える場所が異なります。

1-1. クラスを使ったプログラミング

◯クラスを使いたい

クラスはただのテンプレートなので、そのままでは使うことができません。
なので、

「クラスを具体化してオブジェクトを作り、オブジェクトの特性を活かしつつそれを変数のように扱う」

というふうにしていきます。

◯クラスを具体化する

クラスにはフィールドとメソッドが記述されています。
これをプログラムの中で使いたい。
ですがクラスはただのテンプレートで、抽象的な存在。
なので、クラスを具体的な存在(オブジェクト)にしてそれについて操作していきます。

◯クラスを具体化する方法

簡単な例で見てみましょう。
ここでは、クラスStringからオブジェクトs1をつくっています。

String.java
//オブジェクトの宣言
String s1;
//オブジェクトの定義
s1 = "breakfast"
//オブジェクトの使用
println(s1.length());
9

ここで、s1は
インスタンス(クラスのオブジェクト)
であり
オブジェクト(クラスから作られた具体的な存在)
であり、
インスタンス変数(変数の一種)
です。

どこからみるか、基準をどこにするかによって呼び方(外見)は違いますが、中身は一緒です。
いろいろな呼び方があるんだなあってことです。
人間もいろいろな顔を使い分けているでしょう?(表の顔、裏の顔、上司の前での顔などなど)
それと一緒です。

◯オブジェクトの特性を活かしつつそれを変数のように扱う

全てのオブジェクトはクラスが持つフィールドとメソッドを持っています。

・フィールド = クラスの中で定義される変数

・メソッド = クラスの中で定義される関数

オブジェクトを作ったので、やっとクラスの持つフィールドとメソッドを使えそうです。

オブジェクトの持つフィールドやメソッドにアクセスするためにはドット(.)を使ってアクセスします。
オブジェクト自体は、変数と同じように扱います。

String.java
//オブジェクトの定義
String str1 = "goodjob"; 
//オブジェクトが持つメソッドにアクセスする
str1 = str1.toUpperCase();
//オブジェクトを使用する
println(str1);
GOODJOB

変数と同じように使うとは
定義(宣言→初期設定)→使用
のようにして使うということです。

つまりまとめると、ここでのstr1は

□フィールドやメソッドを持っている。(オブジェクトの特性)
□ドットを使って自身のフィールドやメソッドにアクセスする。(使い方)
かつ
□値、データ型、スコープを持つ。(変数の特性)
□定義(宣言、初期設定)してから使う。(使い方)

以上がクラスを使ったプログラムの方法の一部です。

最後に

読んでいただきありがとうございました。
より良い記事にしていくために御意見、ご指摘のほどよろしくお願いいたします。

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

本当にあった怖いClassCastException

テスト対象メソッドのインターフェース
public class Foo {
    public void process(List<String> arg0) {
        /* 後述 */
    }
}
自分で書いた適当なテストコード
List<String> arg0 = Arrays.asList("あ", "い", "う");

Foo foo = new Foo();
foo.process(arg0);

これが何故かClassCastExceptionで落ちる。
テスト対象のソースを見てビックリ。

なんでわざわざキャストしてんだよ
public void process(List<String> arg0) {
    // ↓なんとコンパイル警告すら出ない!
    List<String> ls = (ArrayList) arg0;

    // 以下略
}

コンパイル警告すら出ない恐ろしいコードでしたとさ……

当たり前だけどこっちだと落ちなかった。
(落ちないから良いとは言っていない)

新人が書いたテストコード
List<String> arg0 = new ArrayList<>();
arg0.add("あ");
arg0.add("い");
arg0.add("う");

Foo foo = new Foo();
foo.process(arg0);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】HashMapの最大値を取得する方法

開発環境・バージョン

・ホストOS: Windows10 Home
・ゲストOS: WSL2 Ubuntu20.04
・Java8

目的

keyの型がString, valueの型がIntegerのHashMapの最大値を取得すること

EntrySetメソッドを使って実装します。
以下は実際のコード

public static void main(String[] args) {
  String arr[] = {"a", "a", "a", "a", "b", "b", "b", "c", "c", "d"};
  Map<String, Integer> map = new HashMap<>();

//配列の要素をマップに格納
  for (String string : arr) {
    if (map.get(string) == null) {
      map.put(string, 1);
    } else {
      map.put(string, map.get(string) + 1);
    }
  }

//最大値とそのときのキーを初期化
  String maxKey = null;
  Integer maxValue = 0;

//entrySetメソッドでマップのキーとValueを一つずつ取得
for (Map.Entry<String, Integer> entry : map.entrySet()) {

//最大値とValueを比較してValueが大きければ、そのときのキーとValueを代入
  if (entry.getValue() > maxValue) {
    maxKey = entry.getKey();
    maxValue = entry.getValue();
  }
}
System.out.println(maxKey + " : " + maxValue);

結果

a : 4

無事最大値を取得することができました。
最大値が複数あり全てを取得する場合はリストに格納すればよいでしょう。

entrySetのメリットは一度のループでキーとValueを両方取得できることですね。

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

MapやListを使ってみた

import java.io.*;
import java.util.*;
public class Q {

    //   「1つ以上のスペース、ピリオド、コンマ、セミコロンのどれか」という意味
    //     |は区切ったもののどれかという意味で、\.は単にピリオドです(文字列表記する都合上、バックスラッシュが2つ必要)
    private static final String SEPARATOR = "(\\s+?|\\.|,|;)";
    /**
     * データファイルを開く
     * resources/q003/data.txt
     */
    private static InputStream openDataFile() {
        //getResourceAsStreamメソッドを利用すると、リソースファイル(設定ファイルなどのこと)を簡単に読み込むことができる
        return Q003.class.getResourceAsStream("data.txt");
    }



    public static void main(String[] args){

        // 集計
        //カウントには以下のMap<String, Integer>を使用
        Map<String, Integer> map = new HashMap<>();
        try (
                /*
                ファイルの読み込み  main配下にあるresourcesからファイルを取得している
                 FileReaderを使ってファイルを読み込む場合には、1文字読み込んでは1文字処理して、と言うのを繰り返すため、非常に効率が悪い
                */
                FileReader fr = new FileReader(Q003.class.getResource("data.txt").getFile());

                /*
                ファイルの読み込み
                 なぜ最初からこのクラスを使わないかというと、このクラスはFileReaderクラスを拡張する形で利用するため。
                 FileReaderクラスの持つ基本機能でファイルから読み込みは行うが、
                 それにBufferedReaderクラスをかぶせて使うことでまとめて読み込む機能を持てるようになる
                */
                BufferedReader br = new BufferedReader(fr)){

            /*
            テキストを1行単位で読む
            1行まとめて読むための"readLine"メソッドが用意されている。
            注意する点は、改行文字は読み込んだ文字に含まれない事
            よって1行ごとに、改行を含まないテキストを読み込んでString型の値として返す
            */
            String line;
            //テキストファイルの読み取りの箇所ではreadLine()で行を取得
            while ((line = br.readLine()) != null) {

                /*
                 全て大文字に変換する。
                 */
                String resultline = line.toLowerCase();

                //splitメソッドでword[]に分割して格納していく。
                String[] words = resultline.split(SEPARATOR);

                //繰り返し処理
                for (String word : words) {
                    //もしwordがからでないなら…   文字列が空かどうかを判定する – isEmptyメソッド
                    //分解後に空白1文字が残る場合に備え、単語の出現数のカウントではisEmpty()メソッドを使用
                    if (!word.isEmpty()) {


                        /*
                        containsKeyメソッドは、指定したキーが存在するか確認を行い、キーが存在する場合は「true」を返します
                        Map.containsKey(検索するキー)

                        キー→単語
                        値 →出現数

                        単語wordが与えられたときの処理は以下の考え方。 
                         単語がMapのキーに含まれている場合、出現数を加算する。
                         単語がMapのキーに含まれていない場合、以下をMapに格納する。  
                         キー    word
                         値      1
                         */
                        if (map.containsKey(word)) {
                            /*
                            要素を取り出すためにgetメソッドを使用する。 get(Object key)
                            要素を格納するためにputメソッドを使用する。 put(K key, V value)
                             */
                            int count = map.get(word) + 1;
                            map.put(word, count);
                        } else {
                            map.put(word, 1);
                        }
                    }
                }

            }
        } catch (FileNotFoundException e) {
            System.out.println("ファイルが見つかりませんでした。");
        } catch (IOException e) {
            System.out.println("読み取りに失敗しました。");
        }


        /*
        アルファベット辞書順に並び変えて出力
        条件
            * - "I"以外は全て小文字で扱う("My"と"my"は同じく"my"として扱う)  
            * - 単数形と複数形のように少しでも文字列が異れば別単語として扱う("dream"と"dreams"は別単語)
            * - アポストロフィーやハイフン付の単語は1単語として扱う("isn't"や"dead-end")
         */

        List<String> list = new ArrayList<>();
        int maxLengthOfSpelling = 0;

        for (String key : map.keySet()) {
            list.add(key);

            if (maxLengthOfSpelling < key.length()) {
                maxLengthOfSpelling = key.length();
            }
        }


        /*
        アルファベット順にソート
        "I"以外は全て小文字で扱う("My"と"my"は同じく"my"として扱う)
        Comparatorインターフェースを用いた方法ではソートするための条件をプログラマが決めることができる。
        複雑な条件でのソートやオブジェクトの並び替えを特定のルールに沿って行いたいときは、この方法を用いる
         */
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.compareToIgnoreCase(s2);
            }
        });


        /*
        どこかのタイミングで 格納されているiを見つけ出し、
        toUpperCaseメソッドで、小文字を大文字に変換すると解決する。
        */
        System.out.println("iのインデックスは" + list.indexOf("i") + "です");
        System.out.println("後ろから調べたiのインデックスは"+list.lastIndexOf("i"));
           // list.set(list.indexOf("i"), "I");



        // 全部の値を出力
        String format = "%-" + maxLengthOfSpelling + "s= %3d";
        for (String word : list) {

            int count = map.get(word);
            //出力の回数を制限するなら、ここで if (出現させたい件数 <= count)で可能
                System.out.printf(format, word, count);
                System.out.println();

        }
    }
}

ちなみにこれ、エラー吐きます。
理由は以下の通り。

現在
String resultfoo = foo.toLowerCase();
を記述し、小文字ですべて表記できるようになりました。

次は、Iを大文字で表示できれば完成です。今は、"i"を検索することができたものの
要素数がわからず変更できておりません。

面倒な記述で申し訳ないのですが、
繰り返し処理で特定の値を検索→そのインデックス番号を指定して値を変更したいです。

インデックス番号は分かったのですが、
setメソッドを使用してもエラーを吐きます。

これは検索した文字列にiが含んでいるものがすべて指定されて
それを変えようとするとコンパイルエラーを起こしていると考えます。

if(list.contains("i")) {
System.out.println("配列内に値が存在しています。");
//indexOfメソッドはArrayList中の値を検索し、値を発見した場合はそのインデックスを返す
System.out.println("iのインデックスは" + list.indexOf("i") + "です");
}
list.set(53,"I"); //←エラーの原因







このまま直すなら以下の手順。私は最後の表示をむりくりIにすることで事なきを得ました。

int count = map.get(word);

で、NullPointerになってるみたい。
mapは小文字なのに、wordは大文字のiなので、nullになって・・・

例外は発生する行番号が出てるので、エラー文はしっかり解読しましょう。

--
対応ですが、listのキーを変更せず表示するさいに、"i"のときだけ大文字に変換するか
mapのキーを出力直前に以下のように置き換えればよいです。

map.put("I", map.get("i"));

コメントつけるのは良いんですけど、つけすぎは可読性下がりますね?共同開発なら怒られちゃうので、みなさんは気を付けましょう?

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

意外とわからない文字の入れ替え方法【原理】

Arrayクラスのsortめっちゃべんりですよね。
勝手に昇順で並び替えてくれますし、降順だってお手の物。


ですが、並び替えの本質を知らないとこの先詰むのかなと怖くなって調べました。sortメソッド使わない方法を。

対象のコード

public class Change {

    public static void main(String[] args) {
        ListManager data = new ListManager();

        for (int i = 1; i < 100; i++) {
            /*
            signumに渡した数値によって以下の値が返ります。
            引数がゼロより大きい場合 ⇒1
            引数がゼロの場合 ⇒0
            引数がゼロより小さい場合 ⇒-1
             */
            int num1 = data.compare(i - 1, i);
            switch (num1) {
                case 1:
                    //入れ替える
                    data.exchange(i - 1, i);
                    //後ろから入れ替えていく
                    for (int n = i; n > 0; n--) {
                        int num2 = data.compare(n - 1, n);
                        switch (num2) {
                            case 1:
                                data.exchange(n - 1, n);
                            default:
                                break;
                        }
                    }
                default:
                    break;
            }
        }
        data.checkResult();
    }
}

public class ListManager {
    private int[] dataList;
    private int compareCount;
    private int exchangeCount;

    public ListManager() {
        // データをランダムに作成する
        Random random = new Random();
        dataList = new int[100];
        for (int i = 0; i < dataList.length; i++) {
            dataList[i] = random.nextInt(10000);
        }
    }

    /**
     * 2つのデータを比較
     *
     * @param index1
     * @param index2
     * @return -1:index1のデータが小さい, 1:index2のデータが小さい, 0:同じデータ
     */
    public int compare(int index1, int index2) {
        compareCount++;
        return (int) Math.signum(dataList[index1] - dataList[index2]);
    }

    /**
     * 2つのデータを入れ替え
     *
     * @param index1
     * @param index2
     */
    public void exchange(int index1, int index2) {
        exchangeCount++;
        int tmp = dataList[index1];
        dataList[index1] = dataList[index2];
        dataList[index2] = tmp;
    }

    /**
     * ソートチェック
     */
    public void checkResult() {
        int data = dataList[0];
        for (int i = 1; i < dataList.length; i++) {
            if (data > dataList[i]) {
                throw new RuntimeException("ソートされていない: [" + (i - 1) + "]=" + data + ", [" + i + "]=" + dataList[i]);
            }
            data = dataList[i];
        }
        System.out.println("ソートOK: 比較=" + compareCount + ", 入れ替え=" + exchangeCount);
    }

なんか無駄なコード書いてる気がするので、わかり次第修正します。

1回目のswitchで入れ替えが起こらなかった場合、その時点で見ているインデックス以前は正しく昇順に並んでいることが確定するんですけど、私のコードの場合、1回目のswitchで入れ替えが起ころうが起こらなかろうが、そのインデックス以前の並びをチェックしているため、無駄かなぁと。

以前の並びをチェックするのは、入れ替えが起こったときだけで十分ですかね…。

短くなるように修正してみます。

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

javaの正規表現~知ってて損なし~

javaでは、配列や文字を分解して配列に格納するときがあります。

その時にsplitメソッドを使って分割を行いますが、こんな感じで処理します。(変数名は適当)

private static final String SEPARATOR = "(\\s+?|\\.|,|;)";

String[] words = line.split(SEPARATOR);


"(\s+?|\.|,|;)";とは?

これらは、正規表現というのにあたります。

具体的には、「1つ以上のスペース、ピリオド、コンマ、セミコロンのどれか」という意味です。

|は区切ったもののどれかという意味で、\.は単にピリオドです(文字列表記する都合上、バックスラッシュが2つ必要です)。

OSによって\が¥になったり、\を2回打ってるのにこの画面だと1つしか表示されなかったりします。

という学びでした(=゚ω゚)ノ

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

Java:ResourceBundleのpropertiesファイルを任意の場所に配置する

はじめに

JavaでLocateを使用する際に ResourceBundle を使用することになった。

そこで ResourceBundle 用のpropertiesファイルをresourceディレクトリに配置した際に、対象のファイルが見つからないエラー(java.util.MissingResourceException)が発生したため、任意の場所にpuropertiesファイルを配置するための備忘録を以下に残す。

環境

▼ ディレクトリ構造

image.png

Main.java にて、日本とアメリカのLocaleを用意し、各ロケール用のpropertiesファイルをresourceディレクトリ直下に配置したが、propertiesファイルが見つからないと言われた。

原因は、クラスパスが以下で参照できないでいた為である。

  • C:\tool\pleiades\workspace\gold\bin

ちなみに、上記は次の記述で確認可能である。

Main.java
class Main {
    public static void main(String[] args) {
        System.out.println(System.getProperty("java.class.path"));
}

余談だが、上記のクラスパスの状態でpropertiesファイルを読み込ませるためには main ディレクトリ直下に配置する必要がある。

任意の場所にpropertiesファイルを配置して参照させるために

結論から言うと URLClassLoader を使用する。

Main.java
class Main {
    public static void main(String[] args) throws MalformedURLException {

        File dicDir = Paths.get(".\\resource").toFile(); // ★1

        URLClassLoader urlLoader; // ★2
        urlLoader = new URLClassLoader(new URL[]{dicDir.toURI().toURL()}); // ★3

        Locale localeJp = Locale.JAPAN;
        Locale localeUs = Locale.US;

        List<Locale> locales =
                new ArrayList<Locale>(Arrays.asList(localeJp, localeUs));

        for (Locale locale : locales) {
            ResourceBundle rb =
                    ResourceBundle.getBundle("Source" ,locale ,urlLoader); // ★4

            System.out.println(rb.getString("apple") + rb.getString("orange"));

        }
    }
}

任意の場所に配置したpropertiesファイルを参照する手順は以下の通り。

  1. ★1でpropertiesファイルを配置する場所を指定する。
  2. ★2と★3で1で指定したクラスローダのインスタンスを生成する。
  3. ★4で基底名がSourceのpropertiesファイルを参照する。

これで★1のパスを変更することで任意の場所にpropertiesファイルを参照することが出来るようになった。

おさらい

  • propertiesファイルのパスを指定しない場合:実行するjavaと同じ階層に配置
  • propertiesファイルのパスを指定する場合 :URLClassLoaderを使用する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む