2018年06月10日

Java Iterableインターフェース/Iteratorインターフェースの実装例

JavaでのIterableインターフェース/Iteratorインターフェースの実装例です。

サンプルのコード、クラスPrimeNumbersは整数を与えておくと、Iteratorを介して与えた整数以下のすべての素数を返します。

Iteratorインターフェースがイテレータを実装するためのもので、
Iterableインターフェースは拡張For文へ渡すためのもの、という役割です。

PrimeNumbersクラス
import java.util.Iterator;

/**
* 素数を計算するクラス
*/
public class PrimeNumbers implements Iterable<Integer>, Iterator<Integer> {

/** 与えられた整数 */
private int myNumber;
/** 現在の算出素数 */
private int curPrimeNumber;

/**
* コンストラクタ
* @param myNumber 与えられた整数
*/
public PrimeNumbers(int myNumber) {
super();
this.myNumber = myNumber;
curPrimeNumber = 1;
}

/**
* 要素のイテレータを返す。
* @see java.lang.Iterable#iterator()
*/
@Override
public Iterator<Integer> iterator() {
// 自身のインスタンスを返す
return this;
}

/**
* 反復処理でさらに要素がある場合にtrueを返す。
* @see java.util.Iterator#hasNext()
*/
@Override
public boolean hasNext() {
// 与えられた整数が1以下なら終了
if (myNumber <= 1)
return false;

// 現在の算出素数が与えられた整数に達していれば終了
if (myNumber == curPrimeNumber)
return false;

int counter;
// 前回素数の次の値から開始
counter = curPrimeNumber + 1;

// 開始値から順に素数であるかをチェックする
for (int i = counter; i <= myNumber; i++) {
int j;
for (j = 2; j <= counter; j++) {
// 2から順番に割っていって、割り切れれば抜ける
if ((counter % j) == 0) {
break;
}
}
// 割り切れる値がチェック対象の整数しかなければ素数
if (j == counter) {
curPrimeNumber = counter;
return true;
}
counter++;
}
return false;
}

/**
* 反復処理で次の要素を返す。
* @see java.util.Iterator#next()
*/
@Override
public Integer next() {
// 現在の算出素数を返す
return curPrimeNumber;
}
}
呼び出し方
public class MyClass {
    public static void main(String... args) {

        // 整数を指定
        final int myNumber = 200;
        // 素数クラスを生成
        PrimeNumbers pNum = new PrimeNumbers(myNumber);

        // 指定整数以下の素数をすべて列挙
        for (Integer cur : pNum) {
            System.out.println(cur);
        }
    }
}

なお、拡張For文を使うには当該のクラスにIterable#iterator()の実装があればよく、
Iterator<E>の実装(implements)は必須ではない。
なので以下のような書き方も可能(動作は全く同じ)。
import java.util.Iterator;

/**
* 素数を計算するクラス
*/
public class PrimeNumbers implements Iterable<Integer> {

/** 与えられた整数 */
private int myNumber;
/** 現在の算出素数 */
private int curPrimeNumber;

/**
* コンストラクタ
* @param myNumber 与えられた整数
*/
public PrimeNumbers(int myNumber) {
super();
this.myNumber = myNumber;
curPrimeNumber = 1;
}

/**
* 要素のイテレータを返す。
* @see java.lang.Iterable#iterator()
*/
@Override
public Iterator<Integer> iterator() {

// Iteratorインターフェースの実装
Iterator<Integer> iterator = new Iterator<Integer>() {
/**
* 反復処理でさらに要素がある場合にtrueを返す。
* @see java.util.Iterator#hasNext()
*/
@Override
public boolean hasNext() {
// 与えられた整数が1以下なら終了
if (myNumber <= 1)
return false;

// 現在の算出素数が与えられた整数に達していれば終了
if (myNumber == curPrimeNumber)
return false;

int counter;
// 前回素数の次の値から開始
counter = curPrimeNumber + 1;

// 開始値から順に素数であるかをチェックする
for (int i = counter; i <= myNumber; i++) {
int j;
for (j = 2; j <= counter; j++) {
// 2から順番に割っていって、割り切れれば抜ける
if ((counter % j) == 0) {
break;
}
}
// 割り切れる値がチェック対象の整数しかなければ素数
if (j == counter) {
curPrimeNumber = counter;
return true;
}
counter++;
}
return false;
}

/**
* 反復処理で次の要素を返す。
* @see java.util.Iterator#next()
*/
@Override
public Integer next() {
// 現在の算出素数を返す
return curPrimeNumber;
}
};

// イテレータを返す
return iterator;
}
}
タグ:JAVA
posted by Hiro at 12:06| Comment(0) | プログラム

2018年06月04日

指定フォルダに日付付きでバックアップ

zipファイルなどを指定のフォルダに「YYMMDD/元ファイル名_YYMMDD_HHMMSS」でコピーするVBScriptです。
コンテキストメニューの「送る」にショートカットを置いて使用します。
'指定フォルダに日付付きでバックアップ

Const path = "C:\バックアップ\"

' 引数のチェック
Set args = WScript.Arguments

If args.Count = 0 Then
Msgbox "ファイルをvbsファイルにドラッグアンドドロップしてください。", vbInformation, "情報"
WScript.Quit
End If

Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Set file = fso.GetFile(args(0))

' 読み取り専用を解除
If file.Attributes And 1 Then
file.Attributes = file.Attributes And &HFE
End If

' ファイル名チェック
nameAry = Split(file.Name,".")
If (Ubound(nameAry) <> 1) Then
Msgbox "ファイル名が不適切です。", vbExclamation, "警告"
WScript.Quit
End If

' ファイル名変更
strDate = Replace(FormatDateTime(now, vbShortDate), "/", "")
strTime = Replace(FormatDateTime(now, vbShortTime), ":", "")
file.Name = nameAry(0) & "_" & strDate & "_" & strTime & "." & nameAry(1)

' フォルダ名決定
folder = path & Replace(strDate, "/", "")

' 日付フォルダ存在チェック
If (fso.FolderExists(folder)) Then
' 日付フォルダあり
Else
' 日付フォルダがないため作成
fso.CreateFolder(folder)
End IF

' ファイルコピー
fso.CopyFile file.path, folder & "\", True

' 元ファイル削除(直接)
'fso.DeleteFile file.path, True

' 元ファイルをゴミ箱へ送る
Const ssfBITBUCKET = 10
Set obj = CreateObject("Shell.Application")
Set namesp = obj.Namespace(ssfBITBUCKET)
namesp.movehere file.path

' フォルダを開く
obj.ShellExecute path

Msgbox folder & "\" & " へのバックアップが完了しました。", vbInformation, "情報"

' 終了
WScript.Quit
タグ:VBScript
posted by Hiro at 21:16| Comment(0) | プログラム

2018年06月03日

Eclipse MyBatisの導入方法と使い方

※2018/11/18更新:各ソフトのバージョンを最新にして再編集しました。

環境
 ・Eclipse 4.8
 ・SQL Server 2017 Express

■SQL Server 2017 Expressの準備
 ・「SQL Server 2017 構成マネージャー」から接続先ポートをTPCポート1433に固定にしておく。
 ・ユーザーを事前に作成し、JDBCでテーブルなどへ接続可能にしておく。

■Eclipseからプロジェクトを作成。ここでは「MyProject」とする。
以下のjarをプロジェクトのビルド・パスへ追加する。
(1)JDBCドライバ (サイト)
 今回は「Microsoft JDBC Driver 7.0 for SQL Server 」のmssql-jdbc-7.0.0.jre8.jarを使用。
(2)my Batis (サイト)
 mybatis-3.4.6.jar を公式サイトからダウンロード。

■接続先のデータベースには次のテーブルがあるとする。
CREATE TABLE UserTable(
    userid int PRIMARY KEY,
    name nvarchar(255) NULL,
    address nvarchar(255) NULL,
    birthday datetime2(7) NULL);
■Eclipse プラグインのインストール
ヘルプ>Eclipseマーケットプレース>「MyBatis Generator」で検索し、画面の指示に沿ってインストール。(MyBatis Generator 1.3.7)

■generatorConfig.xmlの自動生成
メニューバー>ファイル>新規>その他>MyBatis>「MyBatis Generator Configuration File」を選択。XMLファイルが生成される。

■generatorConfig.xmlの編集
 サーバ名、DB名、プロジェクト名等を環境に合わせて書き換える。
 (JDBCがSQL Serverの場合はjarファイルへのパスを正しく設定する。)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<classPathEntry location="D:\(jarファイルへのパス)\mssql-jdbc-7.0.0.jre8.jar" />
<context id="context1">
<jdbcConnection connectionURL="jdbc:sqlserver://SERVERNAME\\SQLEXPRESS:1433;database=MYDATABASE;"
driverClass="com.microsoft.sqlserver.jdbc.SQLServerDriver"
userId="???" password="???" />
<javaModelGenerator targetPackage="jp.example.entity"
targetProject="MyProject/src" />
<sqlMapGenerator targetPackage="jp.example.entity.dao"
targetProject="MyProject/src" />
<javaClientGenerator targetPackage="jp.example.entity.dao"
targetProject="MyProject/src" type="XMLMAPPER" />
<table schema="dbo" tableName="UserTable" />
</context>
</generatorConfiguration>
■generatorConfig.xmlを右クリックして、メニューから「実行」→「Run MyBatis Generator」を選択。
ファイルが自動生成される。

■ファイル階層
パッケージエクスプローラを右クリックし、「resource」という名前で「ソースフォルダ」を作る。
同様に「mapper」のソースフォルダを作る。以下のようなフォルダ構成にする。
プロジェクト名
├「src」フォルダ
│ ├ jp.example.entityパッケージ
│ │ │Usertable.java
│ │ └UsertableExample.java
│ └ jp.example.entity.daoパッケージ
│   └UsertableMapper.java
├「resource」フォルダ
│ ├generatorConfig.xml
│ └mybatis-config.xml      //この後、自分で作るファイル
└「mapper」フォルダ
  ├UsertableMapper.xml      //自動生成されたxmlファイルをここに移動
  └VUsertableMapper.xml    //(メソッドを自作する場合、既存のXMLに追加も可能だが、分かり易いようにファイルを分ける)
■mybatis-config.xmlは自動生成されないので自分で作る。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <properties>
     <property name="mapper.url" value="./mapper"/>
  </properties>
  <!--settings>
    <setting name="logImpl" value="LOG4J"/>
  </settings-->
  <environments default="release">
    <environment id="release">
      <transactionManager type="JDBC" />
        <dataSource type="POOLED">
          <property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
          <property name="url" value="jdbc:sqlserver://SERVERNAME\\SQLEXPRESS:1433;database=MYDATABASE;" />
          <!--property name="username" value="${username}"/-->
          <!--property name="password" value="${password}"/-->
          <property name="username" value="???" />
          <property name="password" value="???" />
        </dataSource>
      </environment>
    </environments>
    <mappers>
    <mapper url="file:${mapper.url}/UsertableMapper.xml" />
<!-- ここにXMLを追加 -->
    <!-- mapper url="file:${mapper.url}/VUsertableMapper.xml" /-->
  </mappers>
</configuration>
■自作のSQLの追加方法
UsertableMapper.javaにメッソド追加。VUsertableMapper.xmlに定義を書く。
public class MyClass {
    public static void main(String... args) {
        try (Reader r = Resources.getResourceAsReader("mybatis-config.xml")) {
            Properties properties = new Properties();
            // mybatis-config.xmlでプレースホルダにしておいて、ここで値を入れることも可能
            // properties.setProperty("username", "???????");
            // properties.setProperty("password", "???????");
            SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(r, properties);
            try (SqlSession ss = ssf.openSession()) {
                // Mapperインスタンス作成
                UsertableMapper tmap = ss.getMapper(UsertableMapper.class);
                // Exampleインスタンス作成
                UsertableExample texp = new UsertableExample();
              
                // ケース1:条件を指定してレコード取得
                // 「name='青木'」または「address='大阪府'」のレコード抽出
                texp.createCriteria().andNameEqualTo("青木");
                texp.or().andAddressEqualTo("大阪府");
                List<Usertable> tlist = tmap.selectByExample(texp);
                for (Usertable cur : tlist) {
                    System.out.println(cur.getName());
                }
                // ケース2:レコード挿入・更新
                int newUserId = 9999;
                String newName = "新しい名前";
                Usertable rec = new Usertable();
                texp = new UsertableExample();
                texp.createCriteria().andUseridEqualTo(newUserId);
                // 既存レコードチェック
                if (tmap.countByExample(texp) > 0) {
                    // アップデート
                    rec.setName(newName);
                    tmap.updateByExampleSelective(rec, texp);
                    // update〜SelectiveメソッドはUsertableに代入されたカラムのみアップデートする。
                } else {
                    // インサート
                    rec.setUserid(newUserId);
                    rec.setName(newName);
                    tmap.insert(rec);
                }
                // コミット
                ss.commit();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
タグ:JAVA Eclipse
posted by Hiro at 12:06| Comment(0) | プログラム