前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【随笔】论一个面试题的解决思路

【随笔】论一个面试题的解决思路

作者头像
框架师
发布2022-03-08 18:23:47
1970
发布2022-03-08 18:23:47
举报
文章被收录于专栏:墨白的Java基地墨白的Java基地

前言

是这样的,最近准备跳槽啦,开始面试了,遇到这样一个问题:给你一个无穷字符串类型的 IP ,IP 之间以 分割,类似这样 String ipStr = "192.168.10.222,192.168.10.43,192.168.10.243",现在需要你写一个方法,入参为 ipStr,出参为 ipStr 的最后一个 Ip。 我比较蠢。。。。当面试官问我的时候,我想到的解决方案就是遍历这个数组,然后存入一个集合,根据索引来定位最后一个 IP ,但是面试官讲我这个有性能问题,我自己尝试了一遍,在一千万以内的数据量内,感觉是不存在性能问题的🤣🤣🤣,但是一亿条数据后直接堆溢出了,丢。。。。下面附代码,请多吐槽,让我意识到自己的不足。

遍历list

代码语言:javascript
复制
package com.mobaijun.streamtest;

import org.springframework.util.StopWatch;

import java.util.ArrayList;

/**
 * Software:IntelliJ IDEA 2021.2 x64
 * Author: https://www.mobaijun.com
 * Date: 2022/2/21 16:48
 * ClassName:IpStr
 * 类描述:
 */
public class IpStr {

    /**
     * 计时器
     */
    private static StopWatch stopWatch = new StopWatch();

    public static void main(String[] args) {
        StringBuilder str = new StringBuilder();
        // N
        for (int i = 1; i <= 10000000; i++) {
            str.append(i)
                    .append("." + i)
                    .append("." + i)
                    .append("." + i)
                    .append(",");
        }
        stopWatch.start();
        String s = ipStr(String.valueOf(str));
        stopWatch.stop();
        System.out.println("运算耗时为:" + stopWatch.prettyPrint());
        System.out.println("计算值为: = " + s);
    }

    public static String ipStr(String str) {
        String[] ipList = str.split(",");
        ArrayList<String> arrayList = new ArrayList<>();
        for (String s : ipList) {
            arrayList.add(s);
        }
        str = arrayList.get(arrayList.size() - 1);
        return str;
    }
}
  • 打印结果为:
代码语言:javascript
复制
运算耗时为:StopWatch '': running time = 5084789100 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
5084789100  100%  

计算值为: = 10000000.10000000.10000000.10000000
  • 在运算一亿条数据的时候,直接堆溢出
代码语言:javascript
复制
Exception in thread "main" java.lang.OutOfMemoryError
    at java.lang.AbstractStringBuilder.hugeCapacity(AbstractStringBuilder.java:161)
    at java.lang.AbstractStringBuilder.newCapacity(AbstractStringBuilder.java:155)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:125)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
    at java.lang.StringBuilder.append(StringBuilder.java:136)
    at com.mobaijun.streamtest.IpStr.main(IpStr.java:27)

在经过几个群的讨论后,我换了方式来实现这道题,一种是反转 list,一样影响效率,一种是直接倒叙遍历。

反转List

代码语言:javascript
复制
public class IpStr2 {

    /**
     * 计时器
     */
    private static StopWatch stopWatch = new StopWatch();

    public static void main(String[] args) {
        StringBuilder str = new StringBuilder();
        // N
        for (int i = 1; i <= 10000000; i++) {
            str.append(i)
                    .append("." + i)
                    .append("." + i)
                    .append("." + i)
                    .append(",");
        }
        stopWatch.start();
        String s = ipStr(String.valueOf(str));
        stopWatch.stop();
        System.out.println("运算耗时为:" + stopWatch.prettyPrint());
        System.out.println("计算值为: = " + s);
    }

    public static String ipStr(String str) {
        ArrayList<String> list = new ArrayList<>();
        String[] split = str.split(",");
        for (String s : split) {
            list.add(s);
        }
        // 反转list
        Collections.reverse(list);
        return list.get(0);
    }
}
  • 耗时时间为:
代码语言:javascript
复制
运算耗时为:StopWatch '': running time = 2156518100 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
2156518100  100%  

计算值为: = 10000000.10000000.10000000.10000000

这个结果也不是很理想,只要存入 list 必然有性能问题。

使用substring实现

代码语言:javascript
复制
public class IpStr3 {
    /**
     * 计时器
     */
    private static StopWatch stopWatch = new StopWatch();

    public static void main(String[] args) {

        StringBuilder str = new StringBuilder();
        // N
        for (int i = 1; i <= 10000000; i++) {
            if (i == 10000000) {
                str.append(i)
                        .append("." + i)
                        .append("." + i)
                        .append("." + i);
            } else {
                str.append(i)
                        .append("." + i)
                        .append("." + i)
                        .append("." + i)
                        .append(",");
            }
        }
        stopWatch.start();
        String s = ipStr(String.valueOf(str));
        stopWatch.stop();
        System.out.println("运算耗时为:" + stopWatch.prettyPrint());
        System.out.println("计算值为: = " + s);
    }

    public static String ipStr(String str) {
        int one = str.lastIndexOf(',');
        str = str.substring(one + 1);
        return str;
    }
}
  • 耗时为:
代码语言:javascript
复制
运算耗时为:StopWatch '': running time = 219355000
--------------------------------------------
ns         %     Task name
--------------------------------------------
219355000  100%  
计算值为: = 10000000.10000000.10000000.10000000

这种方式也无法处理亿级数据量,但是同样千万数据已经把时间压缩到 2 秒左右。 目前只有倒序遍历没有测试过,这块有点头大,各位小伙伴有其他实现方案请在下方留言区进行讨论,欢迎指教。后续倒序搞定了,我会附思路和源码。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-02-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 遍历list
  • 反转List
  • 使用substring实现
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档