Java作业-9

JavaFX,文本处理

Comparable接口与Comparator接口之间有什么不同指出?他们分别属于哪一个包?

特征/接口 Comparable Comparator
定义 用于定义对象的自然排序顺序。实现此接口的类可以自动排序。 用于定义两个对象间的比较规则。允许为类定义多种排序规则。
方法 只有一个方法:compareTo(T o) 主要方法:compare(T o1, T o2)。还有其他辅助方法,如reversed()thenComparing()等。
使用场景 类有明确的“自然”排序顺序时使用,如数字、字母顺序。 为某个类定义不同的排序规则,或该类没有自然排序且不希望或无法修改原始类。
所在包 java.lang java.util

如何创建一个整数优先队列?默认情况下,元素如何以优先队列排序?在优先队列中,拥有最小数值的元素会被赋予最高优先级吗?

PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
如果元素类实现了Comparable接口,队列就会根据compareTo方法定义的自然顺序对元素进行排序。
最小数值的元素会被赋予最高优先级

如何创建一个将元素的自然顺序颠倒的优先队列?

在构造函数中传递一个自定义的Comparator对象

public class ReverseOrderPriorityQueue {
    public static void main(String[] args) {
        // 创建一个Comparator,颠倒自然顺序
        Comparator<Integer> reverseOrder = (o1, o2) -> o2.compareTo(o1);

        // 使用自定义Comparator创建PriorityQueue
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(reverseOrder);

        // 添加一些元素进行测试
        priorityQueue.add(10);
        priorityQueue.add(20);
        priorityQueue.add(5);
        priorityQueue.add(1);

        // 循环并删除队列中的每个元素
        while (!priorityQueue.isEmpty()) {
            System.out.println(priorityQueue.remove());
        }
    }
}

HashSet、LinkHashSet和TreeSet之间的区别是什么?

特性 HashSet LinkedHashSet TreeSet
内部数据结构 基于哈希表(HashMap实例) 基于哈希表和双向链表 基于红黑树(自平衡的二叉搜索树)
顺序性 无序 维护插入顺序 按自然排序或指定的Comparator排序
性能 增删查操作通常是 O(1) 增删查操作通常是 O(1),但略慢于HashSet 增删查操作大约是 O(log n)
使用场景 不需要维护元素顺序的快速查找、插入和删除 需要维护元素插入顺序的快速查找、插入和删除 需要按顺序存储元素的情况
所在包 java.util.HashSet java.util.LinkedHashSet java.util.TreeSet

替换,输出是?

A sorted set of geometric objects
area = 20.0
area = 4.0
area = 5021.538

合适的数据结构

21.10 Set或HashSet
21.11 LinkedHashSet
21.12 TreeSet
21.13 普通数组 a[10]
21.14 ArrayList
21.15 LinkedList

修改程序清单20-6,使得一个球在被创建的时候赋给一个2~20的随机半径。当单击“-”按钮时,最大的一个球被移除

package com.example;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollBar;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class BallRemover extends Application {

    @Override
    public void start(Stage primaryStage) {
        // 创建包含多个球的面板
        MultipleBallPane ballPane = new MultipleBallPane();
        ballPane.setStyle("-fx-border-color: #abcdef");

        // 创建添加和减少球体的按钮
        Button btAdd = new Button("+");
        Button btSubtract = new Button("-");
        HBox hBox = new HBox(10);
        hBox.getChildren().addAll(btAdd, btSubtract);
        hBox.setAlignment(Pos.CENTER);

        // 设置按钮的事件处理
        btAdd.setOnAction(e -> ballPane.add());
        btSubtract.setOnAction(e -> ballPane.subtract());

        // 暂停和恢复动画的事件处理
        ballPane.setOnMousePressed(e -> ballPane.pause());
        ballPane.setOnMouseReleased(e -> ballPane.play());

        // 创建并设置滚动条以控制动画速度
        ScrollBar sbSpeed = new ScrollBar();
        sbSpeed.setMax(20);
        sbSpeed.setValue(10);
        ballPane.rateProperty().bind(sbSpeed.valueProperty());

        // 设置面板布局
        BorderPane pane = new BorderPane();
        pane.setCenter(ballPane);
        pane.setTop(sbSpeed);
        pane.setBottom(hBox);

        // 创建和设置场景
        Scene scene = new Scene(pane, 250, 150);
        primaryStage.setTitle("BallRemover");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private class MultipleBallPane extends Pane {
        private Timeline animation;

        public MultipleBallPane() {
            // 初始化动画
            animation = new Timeline(
                    new KeyFrame(Duration.millis(50), e -> moveBall()));
            animation.setCycleCount(Timeline.INDEFINITE);
            animation.play(); // 启动动画
        }

        public void add() {
            // 随机创建一个新球并添加到面板中
            Color color = new Color(Math.random(), Math.random(), Math.random(), 0.5);
            getChildren().add(new Ball(30, 30, Math.random() * 16 + 5, color));
        }

        public void subtract() {
            if (getChildren().size() > 0) {
                // 移除最大的球
                Ball largestBall = (Ball) (getChildren().get(0));
                for (Node node : getChildren()) {
                    Ball ball = (Ball) node;
                    if (ball.getRadius() > largestBall.getRadius()) {
                        largestBall = ball;
                    }
                }
                getChildren().remove(largestBall);
            }
        }

        // 控制动画的播放和暂停
        public void play() {
            animation.play();
        }

        public void pause() {
            animation.pause();
        }

        // 获取动画速度的属性
        public DoubleProperty rateProperty() {
            return animation.rateProperty();
        }

        // 移动场景中的所有球
        protected void moveBall() {
            for (Node node : this.getChildren()) {
                Ball ball = (Ball) node;
                // 检查球是否触碰到边界
                if (ball.getCenterX() < ball.getRadius() || ball.getCenterX() > getWidth() - ball.getRadius()) {
                    ball.dx *= -1;
                }
                if (ball.getCenterY() < ball.getRadius() || ball.getCenterY() > getHeight() - ball.getRadius()) {
                    ball.dy *= -1;
                }

                // 更新球的位置
                ball.setCenterX(ball.dx + ball.getCenterX());
                ball.setCenterY(ball.dy + ball.getCenterY());
            }
        }
    }

    class Ball extends Circle implements Comparable<Ball> {
        private double dx = 1, dy = 1;

        Ball(double x, double y, double radius, Color color) {
            super(x, y, radius);
            setFill(color);
        }

        // 实现比较接口用于排序
        @Override
        public int compareTo(Ball b) {
            return Double.compare(this.getRadius(), b.getRadius());
        }
    }
}

从文本文件中读取单词,并将所有不重复的单词按照升序显示,文本文件作为命令行参数传递

import java.io.File;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Test2102 {
    public static void main(String[] args) throws Exception {
        // 检查命令行参数
        if (args.length != 1) {
            System.out.println("Usage: java Test2102 filename");
            System.exit(1);
        }

        File file = new File(args[0]); // 从命令行参数获取文件名
        Set<String> treeSet = new TreeSet<>();

        if (file.exists()) {
            try (Scanner input = new Scanner(file)) {
                while (input.hasNextLine()) {
                    String line = input.nextLine().trim();
                    // 使用正则表达式分割字符串
                    String[] tokens = line.split("\\s+|\\.|,|\\(|\\)|\"|'|;|-");

                    for (String token : tokens) {
                        if (!token.isEmpty()) { // 检查分割出的字符串是否为空
                            treeSet.add(token);
                        }
                    }
                }
            } catch (Exception ex) {
                System.err.println("Error reading file: " + ex.getMessage());
            }
        } else {
            System.out.println("File " + args[0] + " does not exist");
        }

        // 输出不重复的单词
        System.out.println(treeSet);
    }
}

将一个Java文件转换成一个HTML文件,在HTML中,关键词、注释和字面量分别用粗体的深蓝色、绿色和蓝色显示。使用命令行传递Java文件和HTML文件

import java.util.*;
import java.io.*;

public class Test2105 {
    // Java关键词列表
    static String[] keywordString = {
            "abstract", "assert", "boolean",
            "break", "byte", "case", "catch", "char", "class", "const",
            "continue", "default", "do", "double", "else", "enum",
            "extends", "for", "final", "finally", "float", "goto", "if",
            "implements", "import", "instanceof", "int", "interface",
            "long", "native", "new", "package", "private", "protected",
            "public", "return", "short", "static", "strictfp", "super",
            "switch", "synchronized", "this", "throw", "throws",
            "transient", "try", "void", "volatile", "while",
            "true", "false", "null" };

    public static void main(String[] args) {
        // 检查命令行参数
        if (args.length != 2) {
            System.out.println("Usage: java Test2105 sourceFile targetFile");
            System.exit(1);
        }

        File sourceFile = new File(args[0]);
        File targetFile = new File(args[1]);

        if (!sourceFile.exists()) {
            System.out.println("Source file " + args[0] + " does not exist");
            System.exit(2);
        }

        Set<String> keywordSet = new HashSet<>(Arrays.asList(keywordString));

        // 读取源文件并转换为HTML格式
        try (Scanner input = new Scanner(sourceFile);
                PrintWriter output = new PrintWriter(targetFile)) {

            StringBuffer sb = new StringBuffer("<html><body>");
            while (input.hasNext()) {
                String line = input.nextLine();
                // 处理每一行的内容
                String htmlLine = processLine(line, keywordSet);
                sb.append(htmlLine);
            }
            sb.append("</body></html>");

            output.println(sb.toString());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    // 处理一行文本,转换为HTML格式
    private static String processLine(String line, Set<String> keywordSet) {
        // 使用StringBuilder而不是StringBuffer,因为它在单线程中效率更高
        StringBuilder htmlLine = new StringBuilder();

        // 检查是否为单行注释
        if (line.trim().startsWith("//")) {
            return "<p style=\"color:green\">" + line + "</p>";
        }

        // 分割字符串以处理可能的注释和字面量
        String[] tokens = line.split("\"");

        // 处理每个分割出的部分
        boolean isLiteral = false; // 标记是否处于字符串字面量中
        for (String token : tokens) {
            if (isLiteral) {
                // 字符串字面量用蓝色显示
                htmlLine.append("<font color=blue>\"").append(token).append("\"</font>");
                isLiteral = false;
            } else {
                // 分割非字面量部分以进一步处理关键词和注释
                String[] words = token.split("[\\s+()]");
                for (String word : words) {
                    if (keywordSet.contains(word)) {
                        // 关键词用粗体深蓝色显示
                        htmlLine.append("<font color=darkblue><b>").append(word).append("</b></font>");
                    } else if (word.startsWith("//")) {
                        // 单行注释用绿色显示
                        htmlLine.append("<font color=green>").append(word);
                        // 注释之后的内容全部视为注释
                        htmlLine.append(token.substring(word.length())).append("</font>");
                        break;
                    } else {
                        htmlLine.append(word);
                    }
                    htmlLine.append(" ");
                }
                isLiteral = true;
            }
        }

        // 每一行结束后添加换行标记
        htmlLine.append("<br>");

        return htmlLine.toString();
    }
}