为什么用Scala编写的代码比Java慢6倍?

 鱼鱼de眼泪2012 发布于 2023-01-12 13:15

我不确定在编写scala代码时是否犯了一些错误。
问题是?

    The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × 8 × 9 = 5832.

    73167176531330624919225119674426574742355349194934 96983520312774506326239578318016984801869478851843 85861560789112949495459501737958331952853208805511 12540698747158523863050715693290963295227443043557 66896648950445244523161731856403098711121722383113 62229893423380308135336276614282806444486645238749 30358907296290491560440772390713810515859307960866 70172427121883998797908792274921901699720888093776 65727333001053367881220235421809751254540594752243 52584907711670556013604839586446706324415722155397 53697817977846174064955149290862569321978468622482 83972241375657056057490261407972968652414535100474 82166370484403199890008895243450658541227588666881 16427171479924442928230863465674813919123162824586 17866458359124566529476545682848912883142607690042 24219022671055626321111109370544217506941658960408 07198403850962455444362981230987879927244284909188 84580156166097919133875499200524063689912560717606 05886116467109405077541002256983155200055935729725 71636269561882670428252483600823257530420752963450

    Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?  

博客(http://www.ituring.com.cn/article/111574)说他编写的代码haskell只包含6ms

    import Data.List
    import Data.Char

    main = do
      a <- readFile "008.txt"
      print . maximum . map (product . take 13) . tails $ map digitToInt $ filter isDigit a  

所以我尝试使用scala

    object Main {

      def main(args: Array[String]): Unit = {
        val begin: Long = System.currentTimeMillis()
            val content = Source.fromFile("file/text").filter(_.isDigit).map(_.toInt - '0').toList
            val lists =
              for (i <- 0 to content.size - 13)
                yield content.drop(i).take(13)
            println(lists.maxBy(_.reduce(_ * _)))
        val end: Long = System.currentTimeMillis()
        println(end - begin)
      }
    }  

但是120ms平均而言。我认为问题是I / O,但是我发现它只是花了10ms(我尝试使用FileChannel代替Source,但是并没有节省很多时间)。mapflatmap(for)操作花费的时间最多。

然后,我尝试使用java查看原因是否为JVM。毫不奇怪,java版本运行速度快得多,大约花了20ms

    public static void main(String[] args) throws IOException {
        long begin = System.currentTimeMillis();

        byte[] bytes = Files.readAllBytes(Paths.get("file/text"));
        List list=new ArrayList<>();
        for(int i=0;i=0&&bytes[i]-'0'<=9) list.add(bytes[i]-'0');
        }

        int max=-1;
        List maxList=new ArrayList<>();
        List temp=new ArrayList<>();

        for(int i=0;i<=list.size()-13;i++){
            int value=1;
            for(int j=i;j max) {
                max = value;
                maxList.clear();
                maxList.addAll(temp);
            }
            temp.clear();
        }
        System.out.println(maxList);
        long end = System.currentTimeMillis();
        System.out.println(end - begin);
    }  

我的问题是为什么Scala版本的代码运行得这么慢?

1 个回答
  • 正如@etherous所提到的:在Java版本中使用可变状态,而Scala版本是完全不变的,并且编写效率也较低。他们只是不同。

    您可以尝试避免maxBy,也可以尝试一次迭代保存已计算的结果。这应该更接近您的Java版本。

    val content = Source.fromFile("file/text").filter(_.isDigit).map(_.toLong - '0').toList
    
    val result = (0 to content.size - 13).foldLeft((List.empty[Long], -1l)){case (current @(_, curMax), next) => {
        val temp = content.drop(next).take(13)
        val tempVal = temp.reduce(_*_)
        if(tempVal > curMax) (temp, tempVal) else current
      }
    }
    

    result这里是一个元组,包含十三个数字的列表,_1并且它的乘积为_2,好像您想要两个都一样。

    奖金

    现在,我考虑一下。有一种称为的方法sliding可以完全解决此问题。但是我想它的运行速度与您的Scala代码一样慢。至少这是简短的:)。

    content.sliding(13).maxBy(_.reduce(_*_))
    

    2023-01-12 13:18 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有