笔试必备—Java输入输出流

Java 流

  • 流可以理解为一个数据,输入流表示从一个源读取数据,输出流表示向一个目标写数据

  • Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中

  • Scanner类 提供了一系列的方法,更加直观、易用性高,但 IO 流操作更加高效、灵活

1. 标准输入读取字符流

Java 的控制台输入由 System.in 完成

为了获得一个绑定到控制台的字符流,你可以把 System.in 包装在一个 BufferedReader 对象中来创建一个字符流

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

2. 输入流分词成为标记

StreamTokenizer类,用于解析基本类型的输入流,将其分解成标记(tokens),可以是数字、字符串、标识符等

StreamTokenizer in = new StreamTokenizer(br);

通过使用 StreamTokenizer,我们可以方便地读取和解析控制台输入的数据

StreamTokenizer 类 字段
在这里插入图片描述

StreamTokenizer 类 方法
在这里插入图片描述

根据需求循环获取对应Token:

// 只要没遇到终止符号(ctrl + D)就一直获取
while (in.nextToken() != StreamTokenizer.TT_EOF) { 
	// 这里根据需要循环 + nextToken()方法 获取需要的
	// 数值类型
	double n = in.nval;
	// 字符类型
	String str = in.sval;
}

获取之后,就可以编写具体的算法代码

3. 向标准输出写入字符流

为了向标准输出(这里指控制台)写入数据,我们使用 PrintWriter 类。

PrintWriter 类提供了一个简单的方法来输出数据,并且可以自动处理字符编码转换。

PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

4. 输出到控制台

使用 PrintWriter 的 print 和 println 方法进行输出,一定要记得刷新输出流到控制台,代码最后需要关闭输出流。

// 输出
out.print();
out.println();

// 刷新和关闭输出流
out.flush();
out.close();

5. 用法示例

美团0810秋招第一题:

小美准备登录美团,需要输入密码,小美忘记了密码,只记得密码可能是 n个字符串中的一个。
小美会按照密码的长度从小到大依次尝试每个字符串,对于相同长度的字符串,小美随机尝试,并且相同的密码只会尝试一次。
小美想知道,她最少需要尝试多少次才能登录成功,最多需要尝试多少次才能登录成功。
小美不会重新尝试已经尝试过的字符串。成功登录后会立即停止尝试。
输入描述
第一行输入一个整数 n(1 <= n <= 1000)代表密码字符串的个数。
第二行输入一个只由小写字母组成的字符串 s(1<=|s|<=1000)代表正确的密码。
接下来 n 行,每行输入一个长度不超过 1000的字符串,代表小美记得的密码。
输出描述
在一行上输出两个整数,表示最少和最多尝试次数。
输入
4
ab
abc
ab
ac
ac
输出
1 2

public static void main(String[] args) throws IOException {
	// 最基本最简单的输出方法 但是没有 IO 流高效
    // Scanner scan = new Scanner(System.in);
    // int nums = scan.nextInt(); // 字符串个数
    // scan.nextLine(); // 消耗掉 nextInt 留下来的换行符
    // String ans = scan.nextLine(); // 正确答案

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StreamTokenizer in = new StreamTokenizer(br);
    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

    // 相同的密码只会尝试一次 所以使用 集合 接收字符串
    // 每种长度字符对应的哈希表:(字符长度 :字符集合)
    Map<Integer, Set<String>> pos = new HashMap<>();
    String ans = null;  // 正确答案序列
    while (in.nextToken() != StreamTokenizer.TT_EOF) {
        int n = (int) in.nval;
        in.nextToken();
        ans = in.sval;
        // 循环读取
        for (int i = 0; i < n; i++) {
            in.nextToken();
            String str = in.sval;
            // computeIfAbsent方法:如果指定的键不存在 则使用提供的映射函数新增,
            // 如果键存在,则什么都不做
            pos.computeIfAbsent(str.length(), k -> new HashSet<>()).add(str);
        }
    }
    // 算法
    int[] extracted = extracted(pos, ans);
    out.print(extracted[0] + " " +extracted[1]);
    out.flush(); // 记得刷新和关闭
    out.close();
}

private static int[] extracted(Map<Integer, Set<String>> pos, String ans) {
    // map 放入列表中, pos.entrySet() 返回 一个 Set集合
    List<Map.Entry<Integer, Set<String>>> sortedPos = new ArrayList<>(pos.entrySet());
    // 按照字符长度进行列表排序
    sortedPos.sort(Map.Entry.comparingByKey());
    // 遍历尝试 更新最小最大尝试次数
    int step = 0;
    int MIN = -1, MAX = -1;
    for (Map.Entry<Integer, Set<String>> entry : sortedPos) {
        Set<String> v = entry.getValue();
        if (v.contains(ans)) {
            // 这个长度下包含正确答案
            MIN = step + 1; // 第一次就试到了正确答案
            MAX = step + v.size(); // 所有字符都尝试一遍
        } else {
            // 这个长度下没有正确答案
            step += v.size(); // 需要从短的开始 所以全部都要尝试一遍
        }
    }
    return new int[]{MIN, MAX};
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值