Javaプログラミング:オブジェクト指向設計とアルゴリズムの実装

本記事では、Javaを使用したオブジェクト指向プログラミングの基礎から、コレクションフレームワークや文字列操作を用いたデータ処理まで、実践的な実装例を解説します。

1. クラス設計とカプセル化

データと操作をひとつの単位にまとめるカプセル化の基本です。ここでは、商品情報を管理する Product クラスを定義し、コンストラクタによる初期化と適切なデータアクセスを実装します。不正な値が入らないように、セッターメソッド内でバリデーションを行います。

public class Product {
    private String id;
    private String name;
    private double unitPrice;

    public Product(String id, String name, double price) {
        this.id = id;
        this.name = name;
        setPrice(price); // バリデーションを通じて設定
    }

    public void setPrice(double price) {
        if (price < 0) {
            this.unitPrice = 0;
        } else {
            this.unitPrice = price;
        }
    }

    public double getPrice() {
        return this.unitPrice;
    }

    @Override
    public String toString() {
        return String.format("ID:%s, Name:%s, Price:%.2f", id, name, unitPrice);
    }

    public static void main(String[] args) {
        Product item = new Product("A001", "Laptop", 1200.50);
        System.out.println(item.toString());
        // 負の値を設定しようとするテスト
        item.setPrice(-50);
        System.out.println("Updated Price: " + item.getPrice());
    }
}

2. 継承と抽象クラスの活用

共通の性質を持つオブジェクト群を効率的に管理するために継承を使用します。図形を表す抽象クラス AbstractShape を基底とし、これを継承した CircularShape クラスで具体的な面積計算を実装します。

abstract class AbstractShape {
    public abstract double calculateArea();
}

class CircularShape extends AbstractShape {
    private double radius;

    public CircularShape(double radius) {
        this.radius = radius;
    }

    @Override
    public double calculateArea() {
        return Math.PI * Math.pow(radius, 2);
    }

    public String getDetails() {
        return "Circle[radius=" + radius + "]";
    }
}

public class ShapeDemo {
    public static void main(String[] args) {
        AbstractShape shape = new CircularShape(5.0);
        System.out.println("Shape: " + ((CircularShape)shape).getDetails());
        System.out.printf("Area: %.2f%n", shape.calculateArea());
    }
}

3. 文字列操作とデータ解析

入力されたテキストデータに対して解析処理を行う例です。特定の文字の出現頻度をカウントするロジックを、配列とループ処理を用いて実装します。

import java.util.Scanner;

public class TextAnalyzer {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("解析対象の文字列を入力してください:");
        String inputText = scanner.nextLine();
        scanner.close();

        int alphaCount = 0;
        int digitCount = 0;
        int spaceCount = 0;

        char[] characters = inputText.toCharArray();

        for (char c : characters) {
            if (Character.isLetter(c)) {
                alphaCount++;
            } else if (Character.isDigit(c)) {
                digitCount++;
            } else if (Character.isWhitespace(c)) {
                spaceCount++;
            }
        }

        System.out.println("アルファベット: " + alphaCount);
        System.out.println("数字: " + digitCount);
        System.out.println("空白: " + spaceCount);
    }
}

4. コレクションフレームワークとソート

複数のオブジェクトをリストで管理し、特定の基準(ここでは社員の給与)で並べ替えを行います。Comparable インターフェースを実装することで、自然順序付けを定義します。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class StaffMember implements Comparable<StaffMember> {
    private String name;
    private int salary;

    public StaffMember(String name, int salary) {
        this.name = name;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public int getSalary() {
        return salary;
    }

    @Override
    public int compareTo(StaffMember other) {
        // 給与の降順でソート
        return Integer.compare(other.salary, this.salary);
    }

    @Override
    public String toString() {
        return name + ": " + salary;
    }
}

public class StaffSorter {
    public static void main(String[] args) {
        List<StaffMember> team = new ArrayList<>();
        team.add(new StaffMember("Alice", 50000));
        team.add(new StaffMember("Bob", 70000));
        team.add(new StaffMember("Charlie", 60000));

        Collections.sort(team);

        System.out.println("Sorted by Salary (High to Low):");
        for (StaffMember member : team) {
            System.out.println(member);
        }
    }
}

5. カスタムデータ構造の実装

リストを内部に持つ独自のスタック構造 CustomStack を定義し、データの追加(push)と取り出し(pop)の動作をシミュレートします。

import java.util.LinkedList;

class CustomStack<T> {
    private LinkedList<T> storage = new LinkedList<>();

    public void push(T item) {
        storage.addLast(item);
        System.out.println("Pushed: " + item);
    }

    public T pop() {
        if (storage.isEmpty()) {
            return null;
        }
        return storage.removeLast();
    }

    public boolean isEmpty() {
        return storage.isEmpty();
    }
}

public class StackDemo {
    public static void main(String[] args) {
        CustomStack<Integer> myStack = new CustomStack<>();
        myStack.push(10);
        myStack.push(20);
        myStack.push(30);

        System.out.println("Popping items:");
        while (!myStack.isEmpty()) {
            System.out.println(myStack.pop());
        }
    }
}

6月24日 20:43 投稿