JavaとPythonにおける効率的なデータ操作とアルゴリズムの実装

1. 高効率な乱数生成

現代的なJava開発(JDK 7以降)では、Randomクラスよりも並列処理に強く、より高品質な乱数を提供するThreadLocalRandomの使用が推奨されます。

Java: 指定範囲の乱数生成

/**
 * [min, max) の範囲で整数を生成
 */
public static int getBoundedRandom(int min, int max) {
    return ThreadLocalRandom.current().nextInt(min, max);
}

Java: 重複のないランダム配列(順列)の生成

Stream APIを活用することで、簡潔にユニークな数値配列を作成できます。

public static int[] createUniqueSequence(int limit) {
    return ThreadLocalRandom.current().ints(0, limit)
            .distinct()
            .limit(limit)
            .toArray();
}

2. 配列の分割とスライス

データのサブセットを抽出する操作は、データ前処理において頻繁に発生します。

Java: Arrays.copyOfRange による抽出

int[] source = {10, 20, 30, 40, 50};
// インデックス1から4の前まで(20, 30, 40)をコピー
int[] slice = Arrays.copyOfRange(source, 1, 4);

Python: NumPyによる動的な分割

np.array_splitを使用すると、指定したインデックス位置で配列を複数のセグメントに分割できます。

import numpy as np

data = np.arange(1, 11)
# インデックス2, 5, 8の位置で分割
parts = np.array_split(data, [2, 5, 8])
# 結果: [array([1, 2]), array([3, 4, 5]), array([6, 7, 8]), array([9, 10])]

3. 上位K個の要素(Top-K問題)

大きなデータセットから最大値に近い要素を特定する手法です。

Java: 優先度付きキュー(PriorityQueue)によるインデックス取得

最小ヒープを維持することで、計算量を抑えつつ上位要素を抽出します。

public static List<Integer> getTopKIndices(int[] values, int k) {
    PriorityQueue<Integer> heap = new PriorityQueue<>(Comparator.comparingInt(i -> values[i]));
    
    for (int i = 0; i < values.length; i++) {
        heap.offer(i);
        if (heap.size() > k) {
            heap.poll();
        }
    }
    List<Integer> result = new ArrayList<>(heap);
    Collections.reverse(result);
    return result;
}

Python: heapqモジュールによる簡潔な実装

import heapq

scores = [10, 50, 20, 100, 80]
# 上位2つの要素のインデックスを取得
top_indices = heapq.nlargest(2, range(len(scores)), key=scores.__getitem__)
# 結果: [3, 4]

4. コンテナ内の最大・最小値操作

Java: Stream APIを用いた最大値取得

int[] numbers = {5, 8, 2, 10, 3};
int maxValue = Arrays.stream(numbers).max().orElseThrow();

List<Double> list = Arrays.asList(1.1, 5.5, 3.3);
double maxInList = Collections.max(list);
int maxIdx = list.indexOf(maxInList);

Python: 辞書型における最大値を持つキーの抽出

ranking = {'node_a': 12, 'node_b': 45, 'node_c': 22}
top_key = max(ranking, key=ranking.get)

5. 関数型プログラミング(Python: Map / Filter / Reduce)

リスト内包表記やlambdaを組み合わせることで、ループ処理を抽象化できます。

from functools import reduce

items = [1, 2, 3, 4, 5, 6]

# Filter: 偶数のみ抽出
evens = list(filter(lambda x: x % 2 == 0, items))

# Map: 各要素を2倍にする
doubled = list(map(lambda x: x * 2, items))

# Reduce: 全要素の積を計算
product = reduce(lambda x, y: x * y, items)

6. 重複チェックと頻度集計(Java)

SetやMapを利用した効率的なデータ検証手法です。

重複の有無を確認

public boolean hasDuplicates(int[] input) {
    return Arrays.stream(input).distinct().count() != input.length;
}

要素の出現回数をカウント

Map<Integer, Integer> frequencyMap = new HashMap<>();
for (int num : dataArray) {
    frequencyMap.merge(num, 1, Integer::sum);
}

7. 幾何計算とデータクリッピング(Python)

距離行列の計算(SciPy)

点群間の距離を一括で計算する場合、cdistが非常に高速です。

from scipy.spatial import distance

points = np.array([[0, 0], [1, 1], [2, 2]])
dist_matrix = distance.cdist(points, points, 'euclidean')

値の範囲制限(NumPy Clip)

配列の値を一定の閾値内に収めます(外れ値の処理などに有効)。

raw_values = np.array([10, 50, 100, 150])
# 20未満を20に、120超を120に固定
clipped_values = np.clip(raw_values, 20, 120)

8. 経路探索における隣接ペアの処理

Python 3.10以降のitertools.pairwiseを使用すると、リスト内の連続する要素ペアを簡単に取得できます。

import itertools

route = [101, 105, 108, 110]
for start, end in itertools.pairwise(route):
    print(f"Segment: {start} -> {end}")

タグ: Java Python NumPy Algorithm DataStructures

10月7日 17:25 投稿