rdd.collect()后得到的List排序问题:Exception in thread “main“ java.lang.UnsupportedOperationException

该博客介绍了如何利用Apache Spark处理Apache日志文件,按小时统计访问量。通过Java API实现数据读取、切分、转换为键值对、求和并排序,最终成功输出按访问小时的访问次数。代码运行过程中遇到UnsupportedOperationException问题,通过调整代码解决了此问题,并展示了部分处理后的结果。

跟着视频的写了一个数据统计的demo,实现按小时统计访问量。代码如下

package com.billy.test;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.FlatMapFunction;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.PairFunction;
import scala.Tuple2;

import java.util.*;

public class SparkTest {

    public static void main(String[] args) {
        SparkConf sparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD");
        JavaSparkContext sc = new JavaSparkContext(sparkConf);
        JavaRDD<String> lines = sc.textFile("files/apache.log");

        //数据分片
        JavaRDD<String> words = lines.flatMap(new FlatMapFunction<String, String>() {

            @Override
            public Iterator<String> call(String s) throws Exception {
                return Arrays.asList(s.split(":")[1]).iterator();
            }
        });
        //数据转化为 对
        JavaPairRDD<String,Integer> wordsMap = words.mapToPair(new PairFunction<String, String, Integer>() {
            @Override
            public Tuple2<String, Integer> call(String s) throws Exception {
                return new Tuple2(s,1);
            }
        });
        //求和
        JavaPairRDD<String,Integer> wordsReduce = wordsMap.reduceByKey(new Function2<Integer, Integer, Integer>() {
            @Override
            public Integer call(Integer arg0, Integer arg1) throws Exception {
                return arg0 + arg1;
            }
        });
        //JavaPairRDD<String, Integer> sortByKey = wordsReduce.sortByKey(true);
        List<Tuple2<String, Integer>> collect = wordsReduce.collect();
        System.out.println("collect0: " + collect);

        //collect = new ArrayList(collect);
        System.out.println("collect1: " + collect);

        //System.out.println(sorted);
        Comparator<? super Tuple2<String, Integer>> myComparator = new Comparator<>() {
            @Override
            public int compare(Tuple2<String, Integer> t1, Tuple2<String, Integer> t2) {
                return t1._2.compareTo(t2._2);
            }
        };
        collect.sort(myComparator);
        System.out.println("collect2: " + collect);
    }
}

结果一直报Exception in thread “main” java.lang.UnsupportedOperationException错误,后来参考文章
https://blog.youkuaiyun.com/Tracycater/article/details/77592472?locationNum=2&fps=1
发现由数组转为List有一些坑,然后看rdd.collect()方法的源码发现果然collect返回的是一个array
在这里插入图片描述
因此也需要将collect得到的List转化一下,在上面的代码中,打开
collect = new ArrayList(collect);的注释,然后就不报错了。
打印结果:

collect0: [(06,366), (20,486), (19,493), (15,496), (00,361), (02,365), (04,355), (22,346), (17,484), (13,475), (11,459), (08,345), (14,498), (09,364), (21,453), (18,478), (16,473), (03,354), (07,357), (12,462), (05,371), (01,360), (10,443), (23,356)]
collect1: [(06,366), (20,486), (19,493), (15,496), (00,361), (02,365), (04,355), (22,346), (17,484), (13,475), (11,459), (08,345), (14,498), (09,364), (21,453), (18,478), (16,473), (03,354), (07,357), (12,462), (05,371), (01,360), (10,443), (23,356)]
collect2: [(08,345), (22,346), (03,354), (04,355), (23,356), (07,357), (01,360), (00,361), (09,364), (02,365), (06,366), (05,371), (10,443), (21,453), (11,459), (12,462), (16,473), (13,475), (18,478), (17,484), (20,486), (19,493), (15,496), (14,498)]

apache.log摘要如下:

83.149.9.216 - - 17/05/2015:10:05:03 +0000 GET /presentations/logstash-monitorama-2013/images/kibana-search.png
83.149.9.216 - - 17/05/2015:10:05:43 +0000 GET /presentations/logstash-monitorama-2013/images/kibana-dashboard3.png
83.149.9.216 - - 17/05/2015:10:05:47 +0000 GET /presentations/logstash-monitorama-2013/plugin/highlight/highlight.js
83.149.9.216 - - 17/05/2015:10:05:12 +0000 GET /presentations/logstash-monitorama-2013/plugin/zoom-js/zoom.js
83.149.9.216 - - 17/05/2015:10:05:07 +0000 GET /presentations/logstash-monitorama-2013/plugin/notes/notes.js
83.149.9.216 - - 17/05/2015:10:05:34 +0000 GET /presentations/logstash-monitorama-2013/images/sad-medic.png
83.149.9.216 - - 17/05/2015:10:05:57 +0000 GET /presentations/logstash-monitorama-2013/css/fonts/Roboto-Bold.ttf
83.149.9.216 - - 17/05/2015:10:05:50 +0000 GET /presentations/logstash-monitorama-2013/css/fonts/Roboto-Regular.ttf
83.149.9.216 - - 17/05/2015:10:05:24 +0000 GET /presentations/logstash-monitorama-2013/images/frontend-response-codes.png
83.149.9.216 - - 17/05/2015:10:05:50 +0000 GET /presentations/logstash-monitorama-2013/images/kibana-dashboard.png
83.149.9.216 - - 17/05/2015:10:05:46 +0000 GET /presentations/logstash-monitorama-2013/images/Dreamhost_logo.svg
83.149.9.216 - - 17/05/2015:10:05:11 +0000 GET /presentations/logstash-monitorama-2013/images/kibana-dashboard2.png
83.149.9.216 - - 17/05/2015:10:05:19 +0000 GET /presentations/logstash-monitorama-2013/images/apache-icon.gif
83.149.9.216 - - 17/05/2015:10:05:33 +0000 GET /presentations/logstash-monitorama-2013/images/nagios-sms5.png
83.149.9.216 - - 17/05/2015:10:05:00 +0000 GET /presentations/logstash-monitorama-2013/images/redis.png
83.149.9.216 - - 17/05/2015:10:05:25 +0000 GET /presentations/logstash-monitorama-2013/images/elasticsearch.png
83.149.9.216 - - 17/05/2015:10:05:59 +0000 GET /presentations/logstash-monitorama-2013/images/logstashbook.png
83.149.9.216 - - 17/05/2015:10:05:30 +0000 GET /presentations/logstash-monitorama-2013/images/github-contributions.png
83.149.9.216 - - 17/05/2015:10:05:53 +0000 GET /presentations/logstash-monitorama-2013/css/print/paper.css
83.149.9.216 - - 17/05/2015:10:05:24 +0000 GET /presentations/logstash-monitorama-2013/images/1983_delorean_dmc-12-pic-38289.jpeg
83.149.9.216 - - 17/05/2015:10:05:54 +0000 GET /presentations/logstash-monitorama-2013/images/simple-inputs-filters-outputs.jpg
83.149.9.216 - - 17/05/2015:10:05:33 +0000 GET /presentations/logstash-monitorama-2013/images/tiered-outputs-to-inputs.jpg
83.149.9.216 - - 17/05/2015:10:05:56 +0000 GET /favicon.ico
24.236.252.67 - - 17/05/2015:10:05:40 +0000 GET /favicon.ico
93.114.45.13 - - 17/05/2015:10:05:14 +0000 GET /articles/dynamic-dns-with-dhcp/
93.114.45.13 - - 17/05/2015:10:05:04 +0000 GET /reset.css
93.114.45.13 - - 17/05/2015:10:05:45 +0000 GET /style2.css
93.114.45.13 - - 17/05/2015:10:05:14 +0000 GET /favicon.ico
93.114.45.13 - - 17/05/2015:10:05:17 +0000 GET /images/jordan-80.png
93.114.45.13 - - 17/05/2015:10:05:21 +0000 GET /images/web/2009/banner.png
Exception in thread "main" java.lang.UnsatisfiedLinkError: 'boolean org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(java.lang.String, int)' at org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Native Method) at org.apache.hadoop.io.nativeio.NativeIO$Windows.access(NativeIO.java:645) at org.apache.hadoop.fs.FileUtil.canRead(FileUtil.java:1230) at org.apache.hadoop.fs.FileUtil.list(FileUtil.java:1435) at org.apache.hadoop.fs.RawLocalFileSystem.listStatus(RawLocalFileSystem.java:493) at org.apache.hadoop.fs.FileSystem.listStatus(FileSystem.java:1868) at org.apache.hadoop.fs.FileSystem.listStatus(FileSystem.java:1910) at org.apache.hadoop.fs.FileSystem$4.<init>(FileSystem.java:2072) at org.apache.hadoop.fs.FileSystem.listLocatedStatus(FileSystem.java:2071) at org.apache.hadoop.fs.ChecksumFileSystem.listLocatedStatus(ChecksumFileSystem.java:700) at org.apache.hadoop.mapreduce.lib.input.FileInputFormat.singleThreadedListStatus(FileInputFormat.java:312) at org.apache.hadoop.mapreduce.lib.input.FileInputFormat.listStatus(FileInputFormat.java:274) at org.apache.spark.input.WholeTextFileInputFormat.setMinPartitions(WholeTextFileInputFormat.scala:52) at org.apache.spark.rdd.WholeTextFileRDD.getPartitions(WholeTextFileRDD.scala:54) at org.apache.spark.rdd.RDD.$anonfun$partitions$2(RDD.scala:276) at scala.Option.getOrElse(Option.scala:189) at org.apache.spark.rdd.RDD.partitions(RDD.scala:272) at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:49) at org.apache.spark.rdd.RDD.$anonfun$partitions$2(RDD.scala:276) at scala.Option.getOrElse(Option.scala:189) at org.apache.spark.rdd.RDD.partitions(RDD.scala:272) at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:49) at org.apache.spark.rdd.RDD.$anonfun$partitions$2(RDD.scala:276) at scala.Option.getOrElse(Option.scala:189) at org.apache.spark.rdd.RDD.partitions(RDD.scala:272) at org.apache.spark.rdd.RDD.getNumPartitions(RDD.scala:292) at com.s
最新发布
04-23
<think>好的,我现在需要帮助用户解决在Hadoop和Spark环境下出现的java.lang.UnsatisfiedLinkError错误。根据用户提供的引用信息,这个问题主要出现在Windows系统中,当尝试保存RDD为分区文件时,系统无法创建文件,并报错涉及NativeIO$Windows类的方法找不到。 首先,我需要回忆一下这个错误的常见原因。通常,UnsatisfiedLinkError表示Java虚拟机(JVM)在尝试加载本地库(native library)时失败。对于Hadoop和Spark来说,这可能是因为缺少必要的本地库文件,比如hadoop.dll和winutils.exe,特别是在Windows环境下运行的时候。Hadoop原本是为Linux设计的,所以在Windows上需要额外的配置。 接下来,用户提到他们已经尝试了不同版本的Hadoop(3.2)和对应的hadoop.dll、winutils.exe(版本3.1),但问题依旧存在。引用[2]中提到,用户后来通过System.load手动加载hadoop.dll并重装Java解决了问题。这可能意味着他们的Java环境或路径配置有问题。 我需要整理出可能的解决方案步骤: 1. **确认Hadoop Windows本地库文件**:确保hadoop.dll和winutils.exe的版本与Hadoop版本完全匹配。用户使用的是Hadoop 3.2,所以应寻找对应的3.2版本的这两个文件,而不是3.1。版本不匹配可能导致兼容性问题。 2. **配置系统环境变量**:将hadoop.dll所在的目录添加到系统的PATH环境变量中,并确保Java能够找到这些库。同时,设置HADOOP_HOME环境变量指向Hadoop的安装目录,确保路径中没有空格或特殊字符。 3. **Java安装与兼容性**:检查Java版本是否与Hadoop和Spark兼容。用户提到重装Java解决了问题,可能之前安装的Java版本有问题或者路径配置错误。建议使用64位的Java,因为本地库通常是64位的。 4. **文件权限问题**:在Windows中,可能需要以管理员权限运行Spark应用,或者确保输出目录有写入权限。此外,检查防病毒软件或防火墙是否阻止了文件操作。 5. **代码或配置调整**:在Spark代码中显式设置Hadoop本地库路径,例如在初始化SparkContext之前添加System.setProperty("hadoop.home.dir", "D:\\hadoop"),或者使用System.load加载hadoop.dll。 6. **验证环境配置**:通过运行简单的Hadoop命令(如hadoop version)或Spark的本地模式任务,确认环境配置是否正确,逐步排查问题。 需要提醒用户注意版本匹配的重要性,特别是Hadoop、SparkJava以及本地库文件之间的版本兼容性。同时,路径的正确性和权限设置也是常见的问题点。如果用户按照这些步骤操作后问题仍然存在,可能需要进一步检查日志文件或尝试在干净的环境中重新配置。</think>### Hadoop/Spark环境java.lang.UnsatisfiedLinkError解决方案 #### 问题根源分析 该错误本质是Windows系统缺失Hadoop本地库支持文件,主要涉及三个关键点: 1. 缺少匹配的$hadoop.dll$和$winutils.exe$文件 2. 环境变量配置不正确 3. Java版本兼容性问题[^2] #### 具体解决步骤 **1. 获取正确的本地库文件** - 下载与Hadoop 3.2完全匹配的Windows工具包 - 建议通过官方GitHub仓库获取: ```powershell https://github.com/cdarlint/winutils/tree/master/hadoop-3.2.0 ``` - 确保包含以下核心文件: ``` bin/ |- hadoop.dll |- winutils.exe |- winutils.pdb ``` **2. 配置系统环境变量** ```powershell # 设置环境变量(示例路径) setx HADOOP_HOME "D:\hadoop-3.2.0" setx PATH "%PATH%;%HADOOP_HOME%\bin" # 验证配置 echo %HADOOP_HOME% where hadoop.dll ``` **3. Java环境验证** - 使用64位JDK 8或11(推荐Oracle JDK) - 检查JAVA_HOME路径不含空格: ```powershell # 错误示例(含空格) C:\Program Files\Java\jdk1.8.0_291 # 建议改为 D:\Java\jdk1.8.0_291 ``` **4. 权限配置** - 对Spark输出目录授予完全控制权限: ```powershell icacls D:\spark_output /grant Everyone:(OI)(CI)F ``` - 以管理员身份运行Spark应用 **5. 代码层解决方案(二选一)** ```scala // 方案1:显式加载本地库 System.load("D:\\hadoop-3.2.0\\bin\\hadoop.dll") // 方案2:启动时配置参数 val spark = SparkSession.builder() .config("spark.hadoop.hadoop.home.dir", "D:\\hadoop-3.2.0") .getOrCreate() ``` #### 验证方案 ```scala // 测试代码 val rdd = spark.sparkContext.parallelize(Seq(1,2,3)) rdd.saveAsTextFile("D:/spark_output_test") // 应生成_SUCCESS标记文件和part-00000 ``` #### 典型错误排查表 | 现象 | 解决方案 | |-------|---------| | 空输出目录 | 检查$winutils.exe$执行权限 | | Access denied | 关闭Windows Defender实时保护 | | 版本不匹配错误 | 使用hadoop checknative -a命令验证 | [^1]: 该错误表明Hadoop本地库未正确加载,常见于Windows开发环境 [^2]: 实际案例显示Java环境与本地库的位数匹配是关键(必须同为32位或64位)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值