Javaの文字列操作

Javaの文字列操作に関するメモ書きです

環境

11.0.16.1

文字列調査

equals

equalsメソッドは2つの値が等しいかを調べるメソッドです。 下記サンプルコードのように、2つの文字列が等しいか判定するのに利用します。

public class Main {
  public static void main(String[] args) {
    String s1 = "iamcat";
    String s2 = "iamcat";
    String s3 = "IAmCat";
    if (s1.equals(s2)) {
      System.out.println("s1とs2は等しい");
    }
    // equalsは大文字と小文字を区別する
    if (s1.equals(s3)) {
      System.out.println("s1とs3は等しい");
    }
  }
}

実行結果

s1とs2は等しい

数値の比較では ==演算子 を使用しますが、文字列の比較ではequalsを使用します。 なぜなら文字列のような参照型の場合、==演算子は同じオブジェクトを参照している場合にtrueを返すので、比較される2つの値が同じ文字列であっても別のオブジェクトだとfalseを返してしまうからです。 2つの文字列の値が等しいかを判定するにはequalsメソッドを使用するのが望ましいです。

length

lengthメソッドは文字列の長さを調べるメソッドです。 lengthメソッドは全角文字も半角文字も1文字として数えます。

public class Main {
  public static void main(String[] args) {
    String s1 = "iamcat";
    System.out.println(s1.length());
  }
}

実行結果

6

isEmpty

isEmptyメソッドは空文字かどうかを調べるメソッドです。 length() == 0 と同じ処理をします。

public class Main {
  public static void main(String[] args) {
    String s1 = "iamcat";
    System.out.println(s1.isEmpty());
    String s2 = "";
    System.out.println(s2.isEmpty());
  }
}

実行結果

false
true

文字列検索

contains

containsメソッドは文字列の一部に引数で指定した文字列が含まれるか判定します。

public class Main {
  public static void main(String[] args) {
      String s1 = "iamcat";
      System.out.println(s1.contains("amc"));
  }
}

実行結果

true

startsWith/endsWith

startsWithメソッドは引数で指定した文字列で始まるかを判定します。 一方、endsWithメソッドは引数で指定した文字列で終わるかを判定します。

public class Main {
  public static void main(String[] args) {
      String s1 = "iamcat";
      System.out.println(s1.startsWith("i"));
      System.out.println(s1.endsWith("t"));
  }
}

実行結果

true
true

indexOf

indexOfメソッドは文字列が最初に登場する位置を返すメソッドです。 文字列の数え方は先頭を0文字目として数えます。

public class Main {
  public static void main(String[] args) {
      String s1 = "iamcat";
      System.out.println(s1.indexOf("amc"));
  }
}

実行結果

1

文字列切り出し

charAt

charAtメソッドは指定位置の1文字を切り出して返します。 charAtも先頭を0文字目として数えます。

public class Main {
  public static void main(String[] args) {
      String s1 = "iamcat";
      System.out.println(s1.charAt(4));
  }
}

実行結果

a

substring

substringメソッドは指定位置から始まる文字列を任意の長さだけ切り出します。 引数を1つだけ指定した場合、指定位置から後ろにある文字列が全て返されます。 引数を2つ指定した場合、2つの指定位置の間にある部分文字列が返されます。

public class Main {
  public static void main(String[] args) {
     // 引数1つの場合
      String s1 = "iamcat";
      System.out.println(s1.substring(2));
      // 引数2つの場合
      System.out.println(s1.substring(2,4));
  }
}

実行結果

mcat
mc

文字列置換

toLowerCase/toUpperCase

toLowerCaseメソッドは大文字を小文字に変換します。 逆に、toUpperCaseメソッドは小文字を大文字を変換します。

public class Main {
  public static void main(String[] args) {
      String s1 = "iamcat";
      System.out.println(s1.toUpperCase());
      String s2 = s1.toUpperCase();
      System.out.println(s2.toLowerCase());
  }
}

実行結果

IAMCAT
iamcat

trim

trimメソッドは文字列の前後の空白を削除します。 半角スペース、改行文字、タブを削除することができますが、全角スペースは削除できません。

public class Main {
  public static void main(String[] args) {
      // 半角スペースを削除
      String s1 = "  iamcat  ";
      System.out.println(s1);
      System.out.println(s1.trim());
      // タブを削除
      String s2 = "\t iamcat";
      System.out.println(s2);
      System.out.println(s2.trim());
      // 改行文字を削除
      String s3 = "\n iamcat";
      System.out.println(s3);
      System.out.println(s3.trim());
  }
}

実行結果

  iamcat  
iamcat
     iamcat
iamcat

 iamcat
iamcat

文字列連結

StringBuilder

StringBuilderメソッドは文字列同士を連結することができます。 +演算子でも文字列連結できますが、連結する数が多い場合、StringBuilderを使用したほうがパフォーマンスが良くなる場合が多いです。 ↓参考 [Java] Stringの結合について

public class Main {
  public static void main(String[] args) {
      // +演算子で連結
      String s1 = "iamcat" + "dog";
      System.out.println(s1);
      // stringBuilderで連結
      StringBuilder s2 = new StringBuilder();
      s2.append("iamcat");
      s2.append("dog");
      System.out.println(s2.toString());
  }
}

実行結果

iamcatdog
iamcatdog

Vue.jsのフィルターを使ってテキストをフォーマットする【Vue2】

環境

Vue:2.6.11

内容

Vue.jsのフイルターという機能を使うことで、画面に表示されるテキストを自由にフォーマットすることができます。

ローカルフィルター

<template>
  <table>
    <p
      {{sample | lowerCase}}
    </p>
  </table>
</template>
<script>
export default {
  data() {
    return {
    // この文字列を小文字化する
      sample:"VUESAMPLE"
    }
  },
    // フィルター
    filters:{
    lowerCase(value){
      return value.toLowerCase();
    }
  },
}
</script>

ローカルコンポーネント内でフィルターを実装したい場合、<script>内で filters: { } と記述し、中に関数を記述してフォーマット処理をreturnすることでフィルターを実装することができます。

上記のケースではJSのライブラリ「toLowerCase」を使って、対象となる値を小文字に変換するフィルターを作ってます。

templeteでは{{}}で値の右隣にパイプ記号を書き、そのまた右隣にフィルターを書くことで適用させます。{{sample | lowerCase}}

VUESAMPLEを小文字変換できました

グローバルフィルター

import Vue from "vue";
import "@babel/polyfill";
import App from "./App.vue";
import router from "./router";
import store from "./store";

require("./assets/scss/app.css");

Vue.config.productionTip = true;
import "./global_config";

// フィルター
Vue.filter("lowerCase", function(value){
  return value.toLowerCase();
}

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount("#app");

12~14行目でフィルターを実装しています。

Vue.filterの1つ目の引数にフィルター名を記述し、2つ目の引数に関数でフィルターの処理を記述します。

computedとの違いについて

computedでも同じような処理を実装することができます。

ではフィルターとの違いは何でしょうか。computedの場合は1つのdataにしか処理が適用できません。

例を示します。

<template>
  <table>
    <p
      {{lowerCase}}
    </p>
  </table>
</template>
<script>
export default {
  data() {
    return {
      sample:"VUESAMPLE"
    }
  },
    computed:{
    lowerCase(){
      return this.sample.toLowerCase();
    }
  },
}
</script>

filterをcomputedで書き換えましたが同じように小文字変換ができています。

しかしdataのsample以外も小文字変換をしたい場合、computedだとその分処理を記述しなければなりません。

<template>
  <table>
    <p
      {{lowerCase}}
      {{lowerCase2}}
    </p>
  </table>
</template>
<script>
export default {
  data() {
    return {
      sample:"VUESAMPLE",
      sample2:"TEST"
    }
  },
    computed:{
    lowerCase(){
      return this.sample.toLowerCase();
    },
    lowerCase2(){
      return this.sample2.toLowerCase();
    }
  },
}
</script>

上記のようにsample2のためにcomputedの処理を増やす必要があります。なぜならcomputedは引数がとれないため、1つのcomputedで複数のdataに適用できないためです。

一方フィルターですと、{{sample2 | lowerCase}} と対象の値にフィルターを適用させるだけでよいので処理の記述は1つだけで済みます。

Vue.jsで定数をコンポーネント外のファイルで一括管理する方法【Vue2】

環境

Vue:2.6.11

内容

Vue.jsで、どのコンポーネントからでも呼び出し可能な定数を定義したいとき、コンポーネント外のjsファイルで一括管理することができます。

1. script内で定数を使用したい場合

srcの下にconsts/const.jsを作成します。

src/consts/const.js

export default Object.freeze({
  SAMPLE_VALUE:"テストバリュー",
});

Object.freezeを使用することで、外部で値を書き換え不可にできます。

コンポーネント側で呼び出します。

src/views/sample.vue

<template>
  <div>
    <button @click="test">
      テストボタン
    </button>
  </div>
</template>
<script>
import constant from "@/consts/const";
export default {
  methods: {
    test(){
      console.log(constant.SAMPLE_VALUE);
    }
  }
}
</script>

import constant from "@/consts/const" でconst.jsを読み込みます。

constant.SAMPLE_VALUE で定数にアクセスします。

テストボタンを押下するとコンソールにSAMPLE_VALUEの値が表示されます。

constant.SAMPLE_VALUEの値を書き換えようとするとエラーが出て書き換え不可となっています。

methods: {
    test(){
      console.log(constant.SAMPLE_VALUE);
      constant.SAMPLE_VALUE = "代入";
    }
  },

2.template内で定数を使用したい場合

const.jsを読みこむためのjsファイルをmixinに作成します。

src/mixins/constLoad.js

export default function(constants) {
  return {
    created: function() {
      for (const [key, value] of Object.entries(constants)) {
        this[key] = value;
      }
    }
  };
}

コンポーネント側です。

src/views/sample.vue

<template>
  <div>
    <button @click="test">
      テストボタン
    </button>
    <span>
      {{constant.SAMPLE_VALUE}}
    </span>
  </div>
</template>
<script>
import constant from "@/consts/const";
import constLoad from "@/mixins/constLoad";
export default {
  methods: {
    test(){
      console.log(constant.SAMPLE_VALUE);
    }
  },
  mixins: [constLoad({ constant })]
}

import constLoad from "@/mixins/constLoad でconstLoadを読み込み、

mixins: [constLoad({ constant })] でconstLoadの引数にconstantを渡します。

定数の値を画面に表示することができました。

mixinを使ってデータをコンポーネント間で共有化する【Vue2】

環境

Vue:2.6.11

内容

mixinを使うことで、export default { } 内に記述するdataやmethodsなどを複数のコンポーネント間で共有することができます。

例えばどのコンポーネントでも使用したいmethodsがあったとして、それぞれのコンポーネントに同じmethodsを記述する必要はなく、mixinに記述することでどのコンポーネントからでも呼び出せるmethodsを設定できます。

sample.vueとsample2.vueのファイルを用意します。

sample.vue

<template>
 <div>
   <p>sample</p>
   <button @click="alert">sampleのテストボタン</button>
   <sample-2> </sample-2>
 </div>
</template>

<script>
import Sample2 from "./sample2.vue";
export default {
 data() {
   return {};
 },
 components: {
   Sample2,
 },
 computed: {},
 methods: {},
};
</script>
<style scoped>
</style>

sample2.vue

<template>
 <div>
   <p>sample2</p>
   <button @click="alert">sample2のテストボタン</button>
 </div>
</template>
 
<script>
export default {
 data() {
   return {};
 },
 computed: {},
 methods: {},
};
</script>
<style scoped>
</style>

画面の状態

どちらもボタンのクリックイベントにalertを紐付けていますが、alertメソッドを実装していないためクリックしても何も起こりません。

では、mixinファイルを作成してalertメソッドを実装してみます。

vueファイルの同階層にalertSample.jsを作成します。

alertSample.jsにalertメソッドを記述します。

alertSample.js

export const alertSample = {
 methods: {
   alert() {
     alert("ボタンがクリックされました");
   },
 },
};

このalertSample.jsをそれぞれのコンポーネントで読み込みます。

import { alertSample } from "./alertSample"; でインポートした後、

mixins: [alertSample] と記述することでmixinファイルをコンポーネントに読み込むことができます。 sample.vue

<template>
 <div>
   <p>sample</p>
   <button @click="alert">sampleのテストボタン</button>
   <sample-2> </sample-2>
 </div>
</template>
 
<script>
import Sample2 from "./sample2.vue";
import { alertSample } from "./alertSample";
export default {
 data() {
   return {};
 },
 components: {
   Sample2,
 },
 mixins: [alertSample],
 computed: {},
 methods: {},
};
</script>
<style scoped>
</style>

sample2.vue

<template>
 <div>
   <p>sample2</p>
   <button @click="alert">sample2のテストボタン</button>
 </div>
</template>
 
<script>
import { alertSample } from "./alertSample";
export default {
 data() {
   return {};
 },
 computed: {},
 mixins: [alertSample],
 methods: {},
};
</script>
<style scoped>
</style>

これでどちらのコンポーネントもalertSample.jsの読み込みが完了しました。

sample.vue、sample2.vueどちらのボタンを教えてもアラートメッセージが表示されます。

sample.vue

sample2.vue

computedとmethodの違いについて【Vue2】

環境

Vue:2.6.11

内容

computedはVue.jsで使用できる算出プロパティです。データの変更を感知して算出後の値をreturnする機能を持ちます。

下記のコードではcomputedを{{ "computed:" + countOverThreeComputed }}で記述し、countの値が3を超えると表示が切り替わるようにしています。

同じような機能をmethodを使っても実装することができます。

{{ "method:" + countOverThreeMethod() }}ではmethodを使ってcountOverThreeComputedと同じ動きを実現しています。

<template>
 <div>
   <button @click="increment">+1</button>
   <p>{{ count }}</p>
   <p>{{ "computed:" + countOverThreeComputed }}</p>
   <p>{{ "method:" + countOverThreeMethod() }}</p>
 </div>
</template>
 
<script>
export default {
 data() {
   return {
     count: 0
   };
 },
 computed: {
   countOverThreeComputed() {
     return this.count > 3 ? "3以上" : "3以下";
   },
 },
 methods: {
   countOverThreeMethod() {
     return this.count > 3 ? "3以上" : "3以下";
   },
   increment() {
     this.count++;
   },
 },
};
</script>
<style scoped>
</style>

初期表示 countが4を超えるとどちらも表示が切り替わる

ではcomputedとmethodでは何が違うのでしょうか?

公式リファレンスでは「算出プロパティは、リアクティブな依存関係が更新されたときにだけ再評価されます」とあります。

jp.vuejs.org

上記のコードでいうと、「countOverThreeComputed」はcountが変更されたときのみ実行されるということです。

逆に「countOverThreeMethod」はcountしか参照していないにもかかわらず、count以外の変数が変更されても実行されてしまいます。

変数「otherCount」とotherCountをインクリメントするメソッドを追加し、countOverThreeComputedとcountOverThreeMethodの中にそれぞれconsole.logを記述して動きを見てみます。

<template>
 <div>
   <button @click="increment">+1</button>
   <p>{{ "count " + count }}</p>
   <button @click="incrementOther">+1</button>
   <p>{{ "otherCount " + otherCount }}</p>
   <p>{{ "computed:" + countOverThreeComputed }}</p>
   <p>{{ "method:" + countOverThreeMethod() }}</p>
 </div>
</template>
 
<script>
export default {
 data() {
   return {
     count: 0,
     otherCount: 0,
   };
 },
 computed: {
   countOverThreeComputed() {
     console.log("computed");
     return this.count > 3 ? "3以上" : "3以下";
   },
 },
 methods: {
   countOverThreeMethod() {
     console.log("method");
     return this.count > 3 ? "3以上" : "3以下";
   },
   increment() {
     this.count++;
   },
   incrementOther() {
     this.otherCount++;
   },
 },
};
</script>
<style scoped>
</style>

otherCountが変更されると「countOverThreeComputed」は実行されませんが、「countOverThreeMethod」が実行されてしまいます。

このように、関係のない変数が変更されるたびにmethodの関数も動いてしまうため、プロジェクトの規模が大きくなった場合など、処理がとても重くなります。

まとめ

{{}}内の関数など、computedで記述すべきところをmethodで書くと上記のような問題が起こります。

クリックイベントなどで実行する関数はmethodで良いですが、{{}}内に記述して参照先を感知して動的に値を変更したい場合はcomputedの使用が推奨されています。

v-ifとv-showの違いについて【Vue2】

環境

Vue:2.6.11

内容

Vue.jsのディレクティブv-ifとv-showは、どちらも条件によって画面の描画を切り替える機能を持ちます。

<template> 
  <div>
    <button type="button" @click="test=!test">ボタン</button>
    <p v-if="test">v-ifの表示</p>
    <p v-show="test">v-showの表示</p>
   </div>
</template>
  
<script>
export default {
  data() {
    return {
      test:true
    };
  },
};
</script>

557b8f2f-de98-4739-b93d-3ca0bba88284.png

ボタンを押すことでv-ifとv-showのどちらも非表示にします。

7d137209-eeaa-44bb-9234-871e81abebdd.png

このときの動きをデベロッパーツールで見てみます。

・表示されているとき

4ac2761d-c4ed-4c0b-a2dc-9a6256126e92.png

・非表示のとき

d6700c49-2c9c-4dbc-bb71-37dec173f341.png

v-ifでは要素そのものが消えており、v-showではstyle属性に”dispaly: none”が設定されることで非表示となっています。

v-ifでは要素そのものが消えるため、ボタンなどで頻繁に表示非表示の切り替えを行う場合は重くなってしまいます。一方v-showではfalseでも初期表示で要素の描画が必ず行われるので、v-ifと比べて初期処理表示の処理が遅くなりやすいです。

使い分けとしては、表示非表示を頻繁に切り替えるものはv-showを使い、表示が初期表示からほとんど変わらないものはv-ifを使うようにしています。

リモートリポジトリを作成してローカルの変更内容をリモートに反映(push)する

リモートリポジトリの作成

GitHubのRepositoriesをクリック

f:id:kankisenkowasuo:20200602232627p:plain
Newをクリック

f:id:kankisenkowasuo:20200602232804p:plain
Repository nameにリポジトリの名前を記入し、Public または Privateにチェックを入れる(ほかの人に見られたくない場合はPrivateで)
Initialize this repository with a README はチェックしなくてもOK
Create Repository をクリック

f:id:kankisenkowasuo:20200603000031p:plain
リモートリポジトリが作成される
f:id:kankisenkowasuo:20200603002428p:plain

ローカルリポジトリをリモートにpush

リモートリポジトリのURLとリモートリポジトリを追加するコマンド git remote add が表示されるのでこれをターミナルで実行する


f:id:kankisenkowasuo:20200602234708p:plain

git remote add origin URL

f:id:kankisenkowasuo:20200603003501p:plain

origin URLの形式で remote add することで、次回からpush時にoriginをつけることでURLを省略できる
リモートリポジトリの新規追加ができたらpushを行う

git push -u origin master

'-u'のオプションをつけることで次回以降、origin master にpushするときに git push だけでpushできるようになる
f:id:kankisenkowasuo:20200603002911p:plain
pushできたのでGitHubの画面でpushができているか確認
f:id:kankisenkowasuo:20200603003249p:plain