魔術師見習いのノート

プロフィール

魔術師見習い
Author魔術師見習い-_-.
Twitter魔術師見習い

コンピュータ関係のメモを主に書きます.

MENU

Androidアプリ タイマとハンドラ

投稿日:
タグ:

本稿はAndroidアプリ開発でjava.util.Timerを使った際のメモである.

Android APIとタイマ

Javaではタイマ(java.util.Timer)を使って一定時間毎に特定の処理を行うことができる.しかしタイマ内で,直接アクティビティ内のウィジェットの情報を書き換えることはできない(私の環境では何故かProgressBarは上手くいったが…).このようなコードはコンパイル可能だが,タイマ内の処理でウィジェットの値を書き換えようとした瞬間,アプリがエラー終了する.これを解決するには,android.os.Handlerのインスタンスを使用すれば良い.これを含め,タイマには次の4つのクラスを使用する.

  • java.util.Timer
  • java.util.TimerTask
  • android.os.Handler
  • java.lang.Runnable

java.util.Timer

はじめにjava.util.Timerを使ったサンプルを紹介する.

class Hoge {
	private java.util.Timer timer;

	private class MyTimerTask implements java.util.TimerTask{
 	 	int time_cnt = 0;
                @Override
                public void run()
                {
                        time_cnt++;
                        System.out.println(time_cnt);
			if (time_cnt==10){
			        timer.cancel();
			}
                }
        }
        Hoge()
        {
                timer = new java.util.Timer(true);
                MyTimerTask ttask = new MyTimerTask();
                timer.schedule(ttask, 60000, 60000);
	}
}
java.util.Timerのインスタンスはschedule関数を使用して,ある処理を定期的に実行できる.scheduleの引数はそれぞれ次の通りである.
schedule(java.util.TimerTaskのインスタンス, 最初に実行されるまでの時間, どれぐらい間を置いて実行するか)
時間はミリ秒単位で指定する.

java.util.Timerのインスタンスはcancelを呼び出すことで終了する.

timer.cancel();
終了したタイマはもう一度scheudleを呼び出しても起動できず,再度処理を行うには新たにインスタンスを生成しなければならない.

java.util.Timerとandroid.os.Handler.

以下に実際のサンプルコードを示す.

public class MainActivity extends android.app.Activity {
	private android.widget.TextView text;
	private java.util.Timer timer;
	private final android.os.Handler HANDLER = new android.os.Handler();
	
	private class MyRunnable extends java.lang.Runnable {
	        private Integer time_cnt = 0;
                @Override
                public void run()
                {
			time_cnt++;
        	        text.setText(time_cnt.toString());
			if (time_cnt==10){
        			timer.cancel();
				finish(); // アクティビティの終了
			}
                }		
        }

	private class MyTimerTask extends java.util.TimerTask{
 	 	MyRunnable RUNNABLE = new MyRunnable();
                @Override
                public void run()
                {
                        HANDLER.post(RUNNABLE);
                }
        }
        protected void onCreate(android.os.Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);

                timer = new java.util.Timer(true);
                MyTimerTask ttask = new MyTimerTask();
                timer.schedule(ttask, 60000, 60000);
                }		
        }
このようにMyTimerTaskクラスのrun関数で,android.os.handlerインスタンスのpost関数を呼び出し,引数にjava.lang.Runnable(あるいはそれを継承した)クラスのインスタンスを与える.これにより,定期的にRunnable(あるいはそれを継承した)クラスのインスタンスのrun()が呼び出される.

UML2.4(6) -パッケージ図-

投稿日:
修正日:
タグ:

パッケージ図

パッケージ図は、パッケージとパッケージ間の関係を表現するダイアグラムである。

名称意味
パッケージ
パッケージ
さまざまなダイアグラムをグループ化するための要素のことであり、名前空間の管理も行う。パッケージ内の各要素の関係は、クラス図やコンポジット構造図のような他のダイアグラムで表現でき、パッケージ間の関係はインポートやマージで表現できる。
パッケージ
要素
インポート 別のパッケージに含まれている要素(クラスやインタフェースなど)を読み込むことを表す。矢印がA⇢BならばパッケージAがパッケージBを読み込んでいることを示す。
マージ 既存のパッケージを利用して別のパッケージを新規に作成することを表す。マージとインポートの違いはパッケージ間で名前の衝突が発生した時の解決方法である。
インポート
インポートするパッケージに元々あった要素が隠される。
マージ
両方のクラスの特徴を持つクラスが生成される。

次のようなパッケージ図があるとする。この時、パッケージP0でクラスAの操作opAという定義があり、かつそれをインポートしたパッケージP1でクラスAの操作Bを定義した場合、パッケージP0のクラスAは隠蔽され、P3で利用するクラスAは操作opBしかない。もしパッケージP0をマージしたパッケージP2でクラスAの操作Bを定義した場合、それをインポートしたパッケージP4では操作opAと操作opBの2つの機能を持つクラスとなる。


Javaのパッケージ

Javaでは、パッケージのインポートをimport文を用いて行う。パッケージの生成とimportは次のように行う。

./pkgtest/Hoge.java
パッケージを生成し、そのパッケージにファイル内で定義したクラスやインタフェースを追加する場合、package文を使用する。package文は必ずJavaの本文を記述する前に記述しなければならない。Javaでは,package文を省略した場合は無名パッケージとして扱われる。すなわちJavaのクラスは必ずいずれかのパッケージに属する。
package pkgtest; // 登録

/**
 * クラスHogeの説明
 * @author 魔術師見習い
 */
public class Hoge {
 /**
  * 加算関数
  * @param addee 被加数
  * @param adder 加数
  * @return 加算結果
  */
  public int add(int addee, int adder){
    return addee + adder;
  }
}
./pkgtest/package-info.java
javadocを使用する場合、パッケージの説明はpackage-info.javaというファイルに記述する。
/**
 * パッケージpkgtestの説明
 * 
 */
package pkgtest;
./Fuga.java
パッケージは次のようにimport文を使用して行う。
import pkgtest.Hoge;

public class Fuga {
  public static void main(String args[]){
    Hoge h = new Hoge();
    System.out.println(h.add(1, 3));
  }
}

Tomcat 入門

投稿日:
タグ:

本稿はtomcatの基本的な部分または最低限必要な部分に関するメモである。

Tomcatとは

Tomcatとは,Apacheソフトウェア財団謹製のJavaサーブレットコンテナである。要するにJavaでWebアプリを作成・実行するためのソフトウェアである。

Tomcat実行環境構築

私の環境(Debian)では,Tomcatは次のコマンド一発でインストール可能であった。

user% sudo aptitude install tomcat7

パッケージ管理を使わずともTomcatの公式ページからダウンロードし,それを解凍すればそれでも十分である。ただしその場合はいくつかの環境変数が必要だったり,起動するのに起動スクリプトではなくtomcatホームのbin/startup.shで起動したりする,といった違いがある。

Webアプリの作成

はじめに以下のディレクトリやファイルを作る。

ファイル(ディレクトリ)説明
hello/WEB-INF/web.xml設定ファイル
hello/WEB-INF/classes使用するクラス
hello/WEB-INF/lib使用するライブラリ(JAR)

web.xmlの中身は後述する。

次にWebアプリに必要なページを生成する。

hello/login.html
<!doctype html>
<html>
  <head>
    <title>login</title>
  </head>

  <body>
    <form action="/hello/Top" method="post">
      <input name="username" type="text">
      <input name="pass" type="password">
      <input type="submit">
    </form>
  </body>
</html>
TopServlet.java
import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;

public class TopServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse
    res) throws IOException,ServletException {
        PrintWriter pw = res.getWriter();

        res.setContentType("text/html; charset=UTF-8");

        pw.println("<html>");
        pw.println("<head><title>hoge</title></head>");
        pw.println("<body>");
        pw.println("<h1>" + req.getParameter("username") + "のページ</h1>");
        pw.println("</body>");
	pw.println("</html>");
    }
}
作成したソースファイルをコンパイルしたものをhello/WEB-INF/classes/の下に配置する。
user% javac -classpath /usr/share/tomcat7/lib/servlet-api.jar -d hello/WEB-INF/classes  TopServlet.java
classpathはライブラリのパスを指定するオプションで,-dはクラスファイルを配置するルートを指定するオプションである。-dはなくても良いが,パッケージをユーザが意識しなくて済むので使った方が便利である。
hello/WEB-INF/web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<servlet>
  <servlet-name>Top</servlet-name>
  <servlet-class>TopServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>Top</servlet-name>
  <url-pattern>/Top</url-pattern>
</servlet-mapping>

</web-app>

最後に生成したディレクトリを圧縮する。

user% cd hello/
user% jar -cvf hello.war *

これによって生成されたhello.warをTomcat実行環境のwebapps直下に配置する。

user% mv hello.war /var/lib/tomcat7/webapps/.

そして,Tomcatを起動すればWebアプリが実行される。

user% sudo service tomcat7 start
user% sudo /

特別にポート番号などを指定しない場合,デフォルトでは次のURLにアクセスすれば作成したページにアクセスできる。

http://localhost:8080/hello/login.html

おまけ

HttpServlet
GETとPOST

HTTPやHTMLのFORMタグに出てくるアクセス方法(メソッド)は,それぞれ以下のHttpServletの関数で処理する。

postdoPost
getdoGet
2つのメソッドは返却値を引数も同じであり,ほぼ同じように作成することができる。

initとdestroy

doGetやdoPostはページが開かれる度に処理される。 これに対して,Tomcatの起動時(正しくは最初のアクセス時)と終了時に処理される処理を書きたい場合,それぞれinitメソッドとdestroyメソッドをオーバーライドする。

@Override
public void init throws ServletException (){}

@Override
public void destroy(){}
forward

Webアプリでは,あるアクセスに対して,複数のサーブレットで処理を行いたい場合がある。 そのような時,次のようなコードを記述する。

FirstServlet.java(First)
public class FirstServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse
    res) throws IOException,ServletException {
        String username = req.getParameter("username");
	〜〜
	RequestDispatcher dispatch = request.getRequestDispatcher("/Second");
        req.setAttribute("username", username);
        dispatch.forward(req, res);
    }
}
SecondServlet.java(Second)
public class SecondServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse
    res) throws IOException,ServletException {
        String username = (String)req.getAttribute("username");
        〜〜
    }
}
スコープ
pageサーブレットに要求が来てから,フォワードするかレスポンスを返すまでの間
requestユーザにレスポンスを返すまでの間
session異なるリクエストを超えて保持したい場合に使用される。
applicationWebアプリケーション内
JSP

サーブレットを作成する場合,簡単な内容であればJSPを使用してより簡易に記述することができる。

<%@ page contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>hello</title>
<%
        ArrayList<String> ary = new ArrayList<String>();
        String tbody = "";
        ary.add("hoge");
        ary.add("fuga");        
        ary.add("piyo");        
        for (int i=0;i<3;i++){
          tbody += "<tr><td>" + i + "</td><td>" + ary.get(i) + "</td></tr>";
        }
%>
</head>

<body>
        <!-- 見出し -->
        <div align="center">
	<table>
	<tbody>
	<%= tbody %>
	</tbody>
	</table>
        </div>
</body>
</html>

このファイルが例えばhello/Hello.jspであれば,URLは"http://localhost:8080/hello/Hello"になる。

JSPは,以下のタグと,新たに拡張したタグを記述することで,簡単にサーブレットを作成できる。

<@ ディレクティブ名 属性="値" ... >
ディレクティブ設定を行う。例えばpageディレクティブはエンコード方式やインポートなどを行う。
<@! 〜 %>
宣言Webアプリが起動直後に1回だけ行う処理を記述する(ページを開き直しても処理されない)。
<% 〜; %>
スクリプトレットJavaのコードを記述する。
<%= 〜 %>
評価結果を出力する。
<jsp:〜 >
アクションタグ別ファイルの展開やページフォワードなどサーブレットの処理を行う
暗黙オブジェクト

JSPでは宣言せずに利用できるオブジェクトがいくつかある。以下にいくつか例を挙げる。

  • request
  • response
  • session

例えばrequestはrequest.getParameter("username")のようにして使用できる。

JAXB

投稿日:
タグ:

JavaでXMLを使用する際、JAXB(Java Architecture for XML Binding)を使用すると便利である。

JAXBの基本

ソース
import javax.xml.bind.JAXB;

class Bean {
    /** 属性 */
    private String val;

    /** 属性のセッター */
    public void setVal(String val){this.val = val;}
    /** 属性のゲッター */
    public String getVal(){return val;}
}


class Sample {
    public static void main(String args[]){
	Bean b = new Bean();
	
	b.setVal("hoge");
	JAXB.marshal(b, System.out);
    }
}
実行結果
user% java Sample
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bean>
<val>hoge</val>
</bean>
marshalがエンティティからXMLの文字列やXMLをストリームへ出力する際に使用する。

タグ名を指定

デフォルトではクラス名やメンバ名がタグに使用されるが、これらの値は以下のように指定することもできる。

ソース
import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlElement;

@XmlRootElement(name = "root")
class Bean {
    /** 属性 */
    private String val;


    /** 属性のセッター */
    public void setVal(String val){this.val = val;}
    /** 属性のゲッター */
    @XmlElement(name = "val1")
    public String getVal(){return val;}
}

class Sample {
    public static void main(String args[]){
	Bean b = new Bean();
	
	b.setVal("hoge");
	JAXB.marshal(b, System.out);
    }
}
実行結果
user% java Sample
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<val1>hoge</val1>
</root>

属性を設定

また、次のようにしてメンバを属性として扱うこともできる。

ソース
import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlAttribute;

@XmlRootElement(name = "root")
class Bean {
    /** 属性1 */
    private String val1;
    /** 属性2 */
    private String val2;

    /** 属性1のセッター */
    public void setVal1(String val1){this.val1 = val1;}
    /** 属性1のゲッター */
    @XmlElement(name = "val1")
    public String getVal1(){return val1;}
    /** 属性2のセッター */
    public void setVal2(String val2){this.val2 = val2;}
    /** 属性2のゲッター */
    @XmlAttribute(name = "val2")
    public String getVal2(){return val2;}
}

class Sample {
    public static void main(String args[]){
	Bean b = new Bean();
	
	b.setVal1("hoge");
	b.setVal2("fuga");
	JAXB.marshal(b, System.out);
    }
}
実行結果
user% java Sample
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root val2="fuga">
<val1>hoge</val1>
</root>

ゲッターの代わりに属性にアノテーションを付加

ソース
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.JAXB;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "root")
class Bean {
    @XmlElement(name = "val_1")
    private String val1;
    
    @XmlElement(name = "val_2")
    private String val2;
    
    public void setVal1(String val1){this.val1 = val1;}
    public String getVal1(){return val1;}
    public void setVal2(String val2){this.val2 = val2;}
    public String getVal2(){return val2;}
}


class Sample {
    public static void main(String args[]){
	Bean f = new Bean();
	
	f.setVal1("hoge");
	f.setVal2("fuga");
	JAXB.marshal(f, System.out);
    }
}
実行結果
user% java Sample
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<val_1>hoge</val_1>
<val_2>fuga</val_2>
</root>

XML読み込み

前述までと逆に、XMLの読み込みを行う場合はunmarshal()を使用する。
ソース
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.JAXB;
import java.io.StringReader;

@XmlRootElement(name = "root")
class Bean {
    @XmlElement(name = "val_1")
    private String val1;
    @XmlElement(name = "val_2")
    private String val2;
    
    public void setVal1(String val1){this.val1 = val1;}
    public String getVal1(){return val1;}
    public void setVal2(String val2){this.val2 = val2;}
    public String getVal2(){return val2;}
}

class Sample {
    public static void main(String args[]){
	String s = "hogefuga";
	System.out.println(s);
	
	Bean bean = (Bean)JAXB.unmarshal(new StringReader(s), Bean.class);
	System.out.println(bean.getVal1());
	System.out.println(bean.getVal2());
    }
}
実行結果
user% java Sample
<?xml version="1.0" encoding="UTF-8"
standalone="yes"?><root><val_1>hoge</val_1><val_2>fuga</val_2></root>
hoge
fuga

タグの順番を未指定

import javax.xml.bind.annotation.XmlAccessorOrder;
import javax.xml.bind.annotation.XmlAccessOrder;

@XmlAccessorOrder(XmlAccessOrder.UNDEFINED)
@XmlRootElement(name = "root")
class Bean {
  // 〜
}

Stream メモ

投稿日:
タグ:

JavaのStreamに関するメモ。

Stream API

概要

Java8から導入されたStream APIは、簡単に言ってデータ集合を扱う機能である。 Stream APIを使うとループ文やイテレータでは、冗長な記載しかできなかった文が簡潔に書けることが多い。

ただし、プロジェクト内でうまくルールを決めないと、同じような実装をやるために、さまざまな書き方で書かれることになる。

また、性能的な観点でいると、簡単なデータ集合を扱うだけならば、わざわざStream型を使用するよりも、基本(プリミティブ)型を使ったほうが速い。

ループ文
java Hoge 0.30s user 0.02s system 99% cpu 0.318 total
String[] ary = {"hoge", "fuga", "piyo"};
for (int i=0;i<3;i++){
   System.out.println(ary[i]);
}
Stream API
java Hoge 0.46s user 0.06s system 113% cpu 0.460 total
String[] ary = {"hoge", "fuga", "piyo"};
Stream.of(ary).forEach(System.out::println);

基本

データ集合にはそれに対応するストリームの種類がある。

  • オブジェクト型
    • Stream
  • 基本(プリミティブ)型
    ストリーム対応するプリミティブ型
    IntStreamint
    LongStreamlong
    DoubleStreamdouble

ストリームは上記のStreamやIntStreamクラスなどのstaticメソッドや、配列やコレクション型などのデータ集合をストリームに型変換することで、記載する。

ストリームに0回以上の中間操作というメソッド呼び出しを行い、最後に終端操作と呼ばれるメソッドを呼ぶのがストリームの基本的な考え方である。

以下、0〜20の間の3の倍数の奇数を出力するサンプル。

IntStream.rangeClosed(0, 20)            // ストリームを取得: 0〜20
         .filter((v) -> v%3==0)         // 中間操作: 3の倍数
         .filter((v) -> v%2==1)         // 中間操作: 奇数
         .forEach(System.out::println); // 終端操作:各要素を引数にメソッド呼び出し
メソッドは以下のように記載する。
  • クラス::メソッド
  • オブジェクト::メソッド
当然this::メソッドもある。

レシピ集

要素に対する条件
allMatch(条件)
全て一致
int [] ary = {1, 2, 3, 4, 5};
if (IntStream.of(ary).allMatch((i) -> i > 0)){
  System.out.println("OK");
}
noneMatchというものもある
noneMatch(条件)
int[] v = {0, 0, 0, 0};
if (IntStream.of(v).noneMatch((x) -> x > 0)){
  System.out.println("OK");
}
anyMatch(条件)
いずれかが一致
int [] ary = {1, 2, 3, 4, 5};
if (IntStream.of(ary).anyMatch((i) -> i > 3)){
  System.out.println("OK");
}
多次元配列から1次元配列へ
flatMap(expression)のexpressionにはStreamを返すメソッドを指定する(flatMapToInt()の場合、IntStream)。
オブジェクト型
String[][] ary = {{"a", "b"}, {"c", "d", "e"}};
String[] s = Stream.of(ary).flatMap(Stream::of)
                           .toArray(String[]::new);
String[][][] ary = {{{"a", "b"}, {"c", "d", "e"}},
                    {{"f", "g"},{"h", "i"}}};
String[] s = Stream.of(ary).flatMap(Stream::of)
                           .flatMap(Stream::of)
                           .toArray(String[]::new);
プリミティブ型
int[][] ary = {{123, 456}, {789, 101}};
int[] iary = Stream.of(ary).flatMapToInt(IntStream::of)
	                   .toArray();
int[][][][] ary = {{{{123, 456}, {789, 101}}, {{121, 131}, {415, 161}}}, {{{718, 192}, {212, 132}}}};
int[] iary = Stream.of(ary).flatMap(Stream::of)
	                   .flatMap(Stream::of)
	                   .flatMapToInt(IntStream::of)
	                   .toArray();
型変換
int[]からList<Integer>への型変換
int [] ary = {1, 2, 3, 4, 5};
List<Integer> list = IntStream.of(ary).mapToObj(Integer::new)
                                      .collect(Collectors.toList());
List<Integer>からint[]への型変換
int[] ary = list.stream().mapToInt((v) -> v).toArray();
String[][]からint[]への型変換
String[][] ary = {{"123", "456"}, {"789", "101"}};
int[] iary = Stream.of(ary)
	   .map((x) -> Stream.of(x).mapToInt((y) -> Integer.parseInt(y)).toArray())
	   .flatMapToInt((v) -> IntStream.of(v))
	   .toArray();
int[]からint
int[] ary = {1, 2, 3, 4};
IntStream.of(ary).reduce((b, i) -> b + i).ifPresent(System.out::println);
ListからMapへ
List.of("a", "b", "c").stream().collect(Function.identity(), e -> String.fomat("{%s}", e));
配列・コレクション型の初期化
List<Integer>の作成
List<Integer> ary = IntStream.rangeClosed(1, 5)
                             .mapToObj(Integer::new)
			     .collect(Collectors.toList());
連続する数字のストリーム。range()の範囲は「開始番号 ≦ n < 終了番号」 rangeClosed()の範囲は「開始番号 ≦ n≦ 終了番号
Set<Integer>
List<Integer> ary = IntStream.rangeClosed(1, 5)
                             .mapToObj(Integer::new)
			     .collect(Collectors.toSet());
ArrayList<String>[]
@SuppressWarnings("unchecked")
public static void main(String[] args){
  ArrayList<String>[] ary =
  Stream.generate(ArrayList::new).limit(5).toArray(ArrayList[]::new);
}
数列
乱数配列
double[] ary = DoubleStream.generate(() -> Math.random()).limit(3).toArray();
generate()は無限に続くストリーム。遅延評価されるため、実際に使用する際は基本的にlimit(n)のように使用する分だけを指定する。
  • 0.39132915962622816
  • 0.7227708950486765
  • 0.47467761699532696
配列に変換(1〜4)
int[] a = IntStream.range(1, 5).toArray()
終了値を含める場合(1〜5)
int[] a = IntStream.rangeClosed(1, 5).toArray()
1, 4, 9, 16, 25,..
IntStream.rangeClosed(1, 5).map((x) -> x * x);
2, 4, 6, 8, 10,..
Stream.iterate(2, x -> x + 2).limit(8)
iterate()はlimit()がないと無制限に続く
Stream.iterate(初期値, 増加式)
その他

文字列結合

Java8からString.join()やStringJoinerというクラスが導入された。 これらを使うと文字列結合が非常に便利になる。

また、Streamと組み合わせると更に記載がシンプルになる。

hoge,fuga,piyo,foo
String.join(",", ary);
レコード:{hoge,fuga,piyo,foo}
Stream.of(ary).collect(Collectors.joining(",", "レコード:{", "}"));

Appendix

ストリーム取得
  • Arrays.stream(配列)
  • Stream.of(配列)
  • Stream.of(要素, ...)
  • コレクション型.stream()
中間操作
Stream.filter(expression)
条件に合致するもののみを抽出する
Stream.distinct()
Streamから要素の重複を排除したものを取得する。
Stream.sorted()
Stream.sorted(expression)
ソートしたストリームを取得する
Stream.map(expression)
Stream.mapToInt(expression)
Stream.mapToLong(expression)
Stream.mapToDouble(expression)
IntStream.mapToObj(expression)
LongStream.mapToObj(expression)
DoubleStream.mapToObj(expression)
各要素を別の型に変換する。map()やmapToObj()はStream型を返し、それ以外は対応するストリームを返す(例:mapToInt()であればIntStream)。
Stream.flatMap(expression)
Stream.flatMapToInt(expression)
Stream.flatMapToLong(expression)
Stream.flatMapToDouble(expression)
各要素をストリームとして、それらを結合したものを取得する expressionには対応するストリームを返すメソッドを指定する。
Stream.parallel()
IntStream.parallel()
LongStream.parallel()
DoubleStream.parallel()
並列実行用のストリームを取得する
終端操作
forEachOrdered(expression)
forEach(expression)
メソッド呼び出し。返り値なし。
Stream.count()
Streamの要素数をカウント。返り値は要素数。
IntStream.sum()
LongStream.sum()
Streamの要素を合計する。返り値は和。

一覧