Hadoop的第二个核心组件:MapReduce框架第二节

Hadoop的第二个核心组件:MapReduce框架第二节

  • 六、MapReduce的工作流程原理(简单版本)
  • 七、MapReduce中的序列化机制问题
  • 八、流量统计案例实现(序列化机制的实现)

六、MapReduce的工作流程原理(简单版本)

1、客户端在执行MR程序时,客户端先根据设置的InputFormat实现类去对输入的数据文件进行切片(getSplits),如果没有设置InputFormat实现类,MR程序会使用默认的实现类(TextInputFormat–>FileInputFormat的子类)进行切片规划,生成一个切片规划文件

2、客户端的切片规划文件生成以后,客户端还会把整个MR程序的配置项(Configuration配置),会封装成为一个job.xml文件,同时还会把MR程序的代码包括job.xml文件、切片规划文件提交给资源调度器(YARN/windowsCPU),资源调度器会先分配资源启动MRAPPMaster的进程

3、MRAPPMaster会根据切片规划的切片个数,向资源调度器申请资源启动对应个数的MapTask任务去运行Mapper阶段的计算逻辑

4、MapTask启动成功以后会根据切片规划,借助指定的InputFormat的实现类中createRecoder方法去对应的切片中读取k-v数据,然后交给map方法做处理

5、map方法将切片的k-v数据处理完成,会k-v数据写到一个内存缓冲区中(100M),如果内存缓冲区超过容量的80%,会溢写磁盘,溢写磁盘的时候会根据map输出的key值进行排序,同时还会根据指定的Partitioner分区机制进行分区。溢写文件可能会存在多个,等map阶段执行完成,每一个MapTask对应的多个溢写文件以及缓冲区中还没有溢写的数据整体会进行一次合并,形成一个最终的大文件(分区排序)

6、紧跟着MRAPPMaster会向资源管理器申请资源启动ReduceTask,ReduceTask启动成功会从不同的MapTask的合并的大的溢写文件中去复制对应的分区的数据,ReduceTask会对所有复制过来的数据再进行一次排序。

7、ReduceTask会对排好序的数据按照key进行分组,分好组之后一组相同的key值调用一次reduce方法进行计算,计算完成的数据会借助指定的OutputFormat类(没有指定,默认使用TextOutputFormat类 - FileOutputFormat实现子类)将key-value数据写出到最终的结果文件中part-r-xxxxx

七、MapReduce中的序列化机制问题

MR程序的Map阶段和Reduce阶段都是要求输入的数据和输出的数据必须得是key-value键值对类型的数据,而且key-value必须得是序列化类型的数据。

序列化:将Java中的某种数据类型转成二进制数据

反序列化:将二进制数据转换成某种数据类型

MR程序采用序列化机制的原因:MR程序之所以要求输入和输出的数据是K-V类型的,是因为MR程序是一个分布式计算程序,MR程序可以在多个节点上同时运行的,而且多个计算程序计算出来的结果可能跨节点,跨网络进行数据传输的。如果数据要跨节点跨网络传输,要求数据必须是二进制数据。(MapReduce程序运行中,Mapper阶段和Reducer阶段的输入和输出都是以key-value的格式进行的。同时Mapper和Reducer阶段的任务中需要的数据可能会跨网络或者跨节点传输,因此我们就要求,MR程序运行过程中所有的输入和输出的数据必须都得是可以被序列化的。)

Hadoop在进行Key-Value的序列化的时候,没有采用Java的序列化机制(Serializable、Externalizable),因为Java的序列化机制非常的笨重的,因此Hadoop基于Java的序列化机制方式提供了一种全新的专门适用于MR程序的轻量级的序列化机制。

Hadoop中提供了两个接口:Writable、WritableComparable,Hadoop提供的两个序列化机制。

Writable

  • 只有序列化和反序列化的效果,如果我们自定义的一个数据类型(Java类)要想当MR程序的value使用的话,Java类必须实现Writable接口,重写两个方法(write - 序列化写、readFields - 反序列化读),通过这两个方法规定序列化和反序列化的内容。

  • Writable的使用方式类似于Java中Externalizable序列化机制

WritableComparable

  • 接口除了具备序列化和反序列化的能力以外,还具备一个比较大小关系的方法

  • 如果自定义的数据类型(Java类),想当MR程序中的key值来使用,必须实现此接口,让自定义数据类型既可以进行序列化反序列化还可以进行大小的比较判断。

  • 如果自定义的数据类型只想当作MR程序中的value来使用,只需要实现Writable接口即可,不需要比较大小。

Hadoop常见的序列化类型(Hadoop把Java中包装类和String类型已经给我们封装好了对应的Hadoop序列化类型) —— 实现了WritableComparable接口

Java类型Hadoop Writable类型
booleanBooleanWritable
byteByteWritable
intIntWritable
floatFloatWritable
longLongWritable
doubleDoubleWritable
stringText
mapMapWritable
arrayArrayWritable

【注意】
1、如果以后MR程序运行没有报错,但是输出目录没有任何的内容,一般可能是因为输入和输出的key-value的自定义类型没有实现序列化。
2、如果自定义的JavaBean充当Reducer阶段输出key-value时,最好把toString方法给重写了,否则Reducer最后输出的结果是JavaBean的地址值。

八、流量统计案例实现(序列化机制的实现)

import org.apache.hadoop.io.Writable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Objects;/*** JavaBean:是Java中一种很干净的类,类当中只具备私有化的属性、构造器、getter   setter方法 hashCode  equals方法 toString方法* 实体类:实体类又是一种特殊的JavaBean,当JavaBean是和数据库中数据表对应的类的时候,JavaBean称之为实体类** JavaBean可以自己手动的生成,也可以使用Lombok技术基于注解快速创建Java类*      Lombok使用慎重,Lombok对代码的侵占性是非常大的** 如果自定义的JavaBean要当MR程序的输入和输出的KV值,最好让JavaBean存在一个无参构造器(MR程序底层反射构建这个类的对象)* 如果自定义的JavaBean要去充当Reducer阶段KEY和Value,那也就意味着JavaBean的结果要写到最终的结果文件中,JavaBean的数据往结果文件写的格式还是按照JavaBean的toString方法去写的。*/
public class FlowBean implements Writable {private Long upFlow;//上行流量private Long downFlow;//下行流量private Long sumFlow;//总流量public FlowBean() {}public FlowBean(Long upFlow, Long downFlow, Long sumFlow) {this.upFlow = upFlow;this.downFlow = downFlow;this.sumFlow = sumFlow;}public Long getUpFlow() {return upFlow;}public void setUpFlow(Long upFlow) {this.upFlow = upFlow;}public Long getDownFlow() {return downFlow;}public void setDownFlow(Long downFlow) {this.downFlow = downFlow;}public Long getSumFlow() {return sumFlow;}public void setSumFlow(Long sumFlow) {this.sumFlow = sumFlow;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;FlowBean flowBean = (FlowBean) o;return Objects.equals(upFlow, flowBean.upFlow) && Objects.equals(downFlow, flowBean.downFlow) && Objects.equals(sumFlow, flowBean.sumFlow);}@Overridepublic int hashCode() {return Objects.hash(upFlow, downFlow, sumFlow);}@Overridepublic String toString() {return upFlow + "\t" + downFlow + "\t" + sumFlow;}/*** 序列化写的方法* @param out <code>DataOuput</code> to serialize this object into.* @throws IOException*/@Overridepublic void write(DataOutput out) throws IOException {out.writeLong(upFlow);out.writeLong(downFlow);out.writeLong(sumFlow);}/*** 反序列化读取数据的方法* @param in <code>DataInput</code> to deseriablize this object from.* @throws IOException*/@Overridepublic void readFields(DataInput in) throws IOException {upFlow = in.readLong();downFlow = in.readLong();sumFlow = in.readLong();}
}
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;/*** 现在有一个文件 phone_data.txt,文件中记录着手机号消耗的流量信息* 文件中每一行数据代表一条手机的流量消耗,每一条数据是以\t制表符分割的多个字段组成的* 使用MR程序统计每一个手机号消耗的总的上行流量、总的下行流量、总流量*/
public class FlowDriver {public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException, URISyntaxException {Configuration configuration = new Configuration();configuration.set("fs.defaultFS","hdfs://192.168.31.104:9000");Job job = Job.getInstance(configuration);//设置MR程序默认使用的InputFormat类 —— 负责进行切片  负责读取数据源的数据为key value类型的
//        job.setInputFormatClass(FileInputFormat.class);//默认确实是FileInputFormat   但是是个 抽象类  MR程序默认使用的是这个抽象类的子类FileInputFormat.setInputPaths(job,"/phone_data.txt");//封装Mapper阶段job.setMapperClass(FlowMapper.class);job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(FlowBean.class);//封装Reducer阶段job.setReducerClass(FlowReducer.class);job.setOutputKeyClass(Text.class);job.setOutputValueClass(FlowBean.class);//封装输出结果路径
//        job.setOutputFormatClass(FileOutputFormat.class);//MR程序要求输出路径不能提前存在 如果提前存在就会报错Path path = new Path("/output");//是用来解决输出目录如果存在MR程序报错问题的FileSystem fileSystem = FileSystem.get(new URI("hdfs://192.168.31.104:9000"), configuration, "root");if (fileSystem.exists(path)){fileSystem.delete(path,true);}FileOutputFormat.setOutputPath(job,path);//最后提交程序运行即可boolean b = job.waitForCompletion(true);System.out.println(b?0:1);}
}
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;import java.io.IOException;/*** 读取切片数据,一行数据读取一次  而且读取的key(偏移量) value LongWritable Text* 输出的key(手机号) value 是 Text FlowBean*/
public class FlowMapper extends Mapper<LongWritable, Text, Text, FlowBean> {@Overrideprotected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, FlowBean>.Context context) throws IOException, InterruptedException {String line = value.toString();String[] array = line.split("\t");String phoneNumber = array[1];Long downFlow = Long.parseLong(array[array.length - 2]);Long upFlow = Long.parseLong(array[array.length - 3]);FlowBean flowBean = new FlowBean(upFlow,downFlow,upFlow + downFlow);//需要将这一条数据以手机号为key,以flowBean为value输出给reducecontext.write(new Text(phoneNumber),flowBean);}
}
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;import java.io.IOException;/****/
public class FlowReducer extends Reducer<Text, FlowBean, Text, FlowBean> {@Overrideprotected void reduce(Text key, Iterable<FlowBean> values, Reducer<Text, FlowBean, Text, FlowBean>.Context context) throws IOException, InterruptedException {Long upFlowSum = 0L;Long downFlowSum = 0L;Long sumFlowSum = 0L;for (FlowBean value : values) {upFlowSum += value.getUpFlow();downFlowSum += value.getDownFlow();sumFlowSum =+ value.getSumFlow();//需要以手机号为key,以flowBean为value将结果输出,flowBean需要将我们计算出来总流量信息封装起来FlowBean flowBean = new FlowBean(upFlowSum,downFlowSum,sumFlowSum);context.write(key,flowBean);}}
}

image-20230723154212141

image-20230723154240240

image-20230723154254681

image-20230723154313960

package com.kang.flow02;import com.kang.flow.FlowDriver;
import jdk.nashorn.internal.runtime.regexp.joni.Config;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Partitioner;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;/*** 基于以前统计的手机消耗流量信息的结果文件,要求对结果文件进行二次分析,得到以下结果:* 1、要求对数据中的手机号按照归属地不同进行分区:*       134开头的手机号  0号分区*       135开头的手机号  1号分区*       136开头的手机号  2号分区*       137开头的手机号  3号分区*       其余的手机号     4号分区* 2、同时还要求每一个分区按照消耗的总流量从高到底进行排序*/
public class FlowDriver02 {public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException, URISyntaxException {Configuration configuration = new Configuration();Job job = Job.getInstance(configuration);job.setJarByClass(FlowDriver02.class);job.setInputFormatClass(TextInputFormat.class);FileInputFormat.setInputPaths(job,new Path("/output/part-r-00000"));job.setMapperClass(FlowMapper02.class);job.setMapOutputKeyClass(FlowBean02.class);job.setMapOutputValueClass(NullWritable.class);job.setPartitionerClass(FlowPartitioner.class);job.setReducerClass(FlowReducer02.class);job.setOutputKeyClass(FlowBean02.class);job.setOutputValueClass(NullWritable.class);job.setNumReduceTasks(5);Path path =new Path("/output1");FileSystem fs = FileSystem.get(new URI("hdfs://192.168.31.104:9000"), configuration, "root");if (fs.exists(path)){fs.delete(path);}FileOutputFormat.setOutputPath(job,path);boolean flag = job.waitForCompletion(true);System.exit(flag?0:1);}
}class FlowMapper02 extends Mapper<LongWritable, Text,FlowBean02,NullWritable> {@Overrideprotected void map(LongWritable key, Text value, Mapper<LongWritable, Text, FlowBean02, NullWritable>.Context context) throws IOException, InterruptedException {String line = value.toString();String[] message = line.split("\t");String phoneNumber = message[0];Long upFlow = Long.parseLong(message[1]);Long downFlow = Long.parseLong(message[2]);Long sumFlow = Long.parseLong(message[3]);FlowBean02 flowBean02 = new FlowBean02(phoneNumber,upFlow,downFlow,sumFlow);context.write(flowBean02,NullWritable.get());}
}oneNumber.startsWith("137")) {return 3;}else  {return 4;}
//        String message = flowBean02.toString();
//        String[] array = message.split("\t");
//        String phoneNumber = array[0];
//        char w1 = phoneNumber.charAt(0);
//        char w2 = phoneNumber.charAt(1);
//        char w3 = phoneNumber.charAt(2);
//        if (w1 == '1' && w2 == '3') {
//            if (w3 == '4') return 0;
//            if (w3 == '5') return 1;
//            if (w3 == '6') return 2;
//            if (w3 == '7') return 3;
//        }
//        return 4;}
}class FlowReducer02 extends Reducer<FlowBean02,NullWritable,FlowBean02, NullWritable>{@Overrideprotected void reduce(FlowBean02 key, Iterable<NullWritable> values, Reducer<FlowBean02, NullWritable, FlowBean02, NullWritable>.Context context) throws IOException, InterruptedException {context.write(key,NullWritable.get());}
}package com.kang.flow02;import org.apache.hadoop.io.WritableComparable;import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Objects;public class FlowBean02 implements WritableComparable<FlowBean02> {private String phoneNumber;private Long upFlow;private Long downFlow;private Long sumFlow;public FlowBean02() {}public FlowBean02(String phoneNumber, Long upFlow, Long downFlow, Long sumFlow) {this.phoneNumber = phoneNumber;this.upFlow = upFlow;this.downFlow = downFlow;this.sumFlow = sumFlow;}public String getPhoneNumber() {return phoneNumber;}public void setPhoneNumber(String phoneNumber) {this.phoneNumber = phoneNumber;}public Long getUpFlow() {return upFlow;}public void setUpFlow(Long upFlow) {this.upFlow = upFlow;}public Long getDownFlow() {return downFlow;}public void setDownFlow(Long downFlow) {this.downFlow = downFlow;}public Long getSumFlow() {return sumFlow;}public void setSumFlow(Long sumFlow) {this.sumFlow = sumFlow;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;FlowBean02 that = (FlowBean02) o;return Objects.equals(phoneNumber, that.phoneNumber) && Objects.equals(upFlow, that.upFlow) && Objects.equals(downFlow, that.downFlow) && Objects.equals(sumFlow, that.sumFlow);}@Overridepublic int hashCode() {return Objects.hash(phoneNumber, upFlow, downFlow, sumFlow);}@Overridepublic String toString() {return phoneNumber + "\t" + upFlow + "\t" + downFlow + "\t" + sumFlow;}@Overridepublic int compareTo(FlowBean02 o) {if (this.sumFlow > o.sumFlow){return 1;} else if (this.sumFlow < o.sumFlow) {return -1;}else {return 0;}}@Overridepublic void write(DataOutput out) throws IOException {out.writeUTF(phoneNumber);out.writeLong(upFlow);out.writeLong(downFlow);out.writeLong(sumFlow);}@Overridepublic void readFields(DataInput in) throws IOException {phoneNumber = in.readUTF();upFlow = in.readLong();downFlow = in.readLong();sumFlow = in.readLong();}
}

image-20230726214325943

image-20230726214343317

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/70121.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Lua03——开发环境搭建

1 安装开发插件 在 idea 或 vscode 中安装 lua 的开发插件 EmmyLua 2 创建工程 在 idea 中创建一个新的工程 工程的类型选择 lua 输入工程名及目标目录 在工程结构的SDK中设置lua在本地安装目录 在工程结构的modules中选择 lua 3 编写第一个lua程序 在工程下添加程序包&#…

阿里云服务器怎么退款?云服务器退款流程图

阿里云服务器如何退款&#xff1f;云服务器在哪申请退款&#xff1f;在用户中心订单管理中的退订管理中退款&#xff0c;阿里云百科分享阿里云服务器退款流程&#xff0c;包括申请退款入口、云服务器退款限制条件、退款多久到账等详细说明&#xff1a; 目录 阿里云服务器退款…

解决readme.md文件中粘贴的图片放到GitHub上无法显示问题

问题原因 GitHub的README.md文件通常无法直接引用本地文件或图片&#xff0c;因为GitHub的README.md是在远程服务器上渲染和显示的&#xff0c;无法访问本地文件系统。 解决方案 要在GitHub的README.md中显示图片&#xff0c;你需要将图片上传到GitHub上&#xff0c;然后使用图…

pycharm创建py文件时自动添加基础信息--模板

在图片中加入下面基本信息&#xff0c;这些基本信息可以自己定义&#xff1a; #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : ${DATE} ${TIME} # Author : supermps # File : ${NAME}.py # Software : ${PRODUCT_NAME} import logging import math import w…

TreeList 的 增加、删除节点-----DevExpress

private void FrmDictionaryManaged_Load(object sender, EventArgs e){// treeList1.DataSource CreateDataTable();treeList2.DataSource CreateTreeList();// 绑定TreeList控件到数据源treeList1.DataSource GetData();treeList1.KeyFieldName "ID";treeList1.…

两种解法解决 LeetCode 27. 移除元素【C++】

移除元素 27. 移除元素题目&#xff1a;[移除元素](https://leetcode.cn/problems/remove-element/description/)示例和提示&#xff1a;解法&#xff1a;1. 暴力解法 2. 快慢指针 27. 移除元素 题目&#xff1a;移除元素 示例和提示&#xff1a; 解法&#xff1a; 1. 暴力解…

嵌入式面试/笔试C相关总结

1、存储 单片机端编译后分为code ro rw zi几个区域&#xff0c;其中code是执行文件&#xff0c;ro(read only)只读区域&#xff0c;存放const修饰常量、字符串。rw(read write)存放已初始化变量。zi存放未初始化变量。编译完成后bin大小为coderorw。运行时所需内存为rwzi。 在电…

【狂神】Spring5笔记(四)之Mybatis和事物的整合

一、整合Mybatis方式一 目录结构&#xff1a; 大致内容结构&#xff1a; 主要难点就在于applicationContext.xml中相关配置的理解 代码图片如下 这个类就专门用于对象的创建就可以了 测试类&#xff1a; 实现类&#xff1a; SqlSessionTemplate 二、整合Mybatis方式二 相关代码…

vue3中使用viewerjs实现图片预览效果

vue3中使用viewerjs实现图片预览效果 1、前言2、实现效果3、在vue3项目中使用viewer.js3.1 安装3.2 在main.js中引入3.3 组件中使用 1、前言 viewer.js是一款开源的图片预览插件&#xff0c;功能十分强大: 支持移动设备触摸事件支持响应式支持放大/缩小支持旋转&#xff08;类…

SpringMVC常用注解、参数传递、返回值

目录 前言 一、常用注解 二、参数传递 ​编辑 1. 基础类型String类型 2. 复杂类型 3. RequestParam 4. PathVariable 5.RequestBody 6. RequestHeader 三、方法返回值 一&#xff1a;void 二&#xff1a;String 三&#xff1a;Stringmodel 四&#xff1a;ModelAndVi…

MySQL数据库和表的操作

数据库基础 存储数据用文件就可以了&#xff0c;为什么还要弄个数据库? 文件保存数据有以下几个缺点&#xff1a; 1、文件的安全性问题 2、文件不利于数据查询和管理 3、文件不利于存储海量数据 4、文件在程序中控制不方便 数据库存储介质&#xff1a; 磁盘 内存 为了解决上…

STM32微控制器的低功耗模式

STM32微控制器的低功耗模式(Low-power modes):Sleep mode、Stop mode 和 Standby mode。 1.1 Sleep Mode(睡眠模式): 把STM32微控制器当作一位劳累的工人,他在工作过程中需要短暂的休息。在Sleep模式下,微控制器会关闭一部分电路,减小功耗,但仍然保持对中央处理单…

代码管理记录(二):Github代码上传实操

文章目录 Git介绍通过Git如何将本地代码上传错误汇总 Git介绍 Git是一个分布式版本控制系统&#xff0c;用于跟踪代码的修改和协同开发。它提供了强大的分支管理、版本控制和合并功能。作为一个上传GitHub的工具&#xff0c;Git可以轻松地将本地代码推送到GitHub远程仓库&…

第一天 关于项目遇到的问题和缺少的知识点

1.配置静态资源映射 配置文件使用的都是配置类方式 创建配置类WebMvcConfig,设置静态资源映射 用于在Springboot项目中, 默认静态资源的存放目录为 : "classpath:/resources/", "classpath:/static/", "classpath:/public/" ; 而在我们的项目中静…

SpringMVC入门的注解、参数传递、返回值和页面跳转---超详细教学

前言&#xff1a; 欢迎阅读Spring MVC入门必读&#xff01;在这篇文章中&#xff0c;我们将探索这个令人兴奋的框架&#xff0c;它为您提供了一种高效、灵活且易于维护的方式来构建Web应用程序。通过使用Spring MVC&#xff0c;您将享受到以下好处&#xff1a;简洁的代码、强大…

《向量数据库指南》——AI原生向量数据库Milvus Cloud 2.3新功能

New Feature Upsert 功能 支持用户通过 upsert 接口更新或插入数据。已知限制,自增 id 不支持 upsert;upsert 是内部实现是 delete + insert所以性能上会有一定损耗,如果明确知道是写入数据的场景请继续使用 insert。 Range Search 功能 支持用户通过输入参数指定 search 的…

【算法专题突破】双指针 - 和为s的两个数字(6)

目录 1. 题目解析 2. 算法原理 3. 代码编写 写在最后&#xff1a; 1. 题目解析 题目链接&#xff1a;剑指 Offer 57. 和为s的两个数字 - 力扣&#xff08;Leetcode&#xff09; 这道题题目就一句话但是也是有信息可以提取的&#xff0c; 最重要的就是开始的那句话&#…

【小吉测评】高效简洁的数据库管控平台—CloudQuery

文章目录 &#x1f384;CloudQuery是什么&#x1f6f8;CloudQuery支持的数据源类型&#x1f354;CloudQuery社区地址&#x1f33a;如何使用&#x1f6f8;参考官方文档&#x1f6f8;参考视频教程&#x1f388;点击免费下载&#x1f388;立即下载即可&#x1f388;使用服务器完成…

Android——数据存储(一)(二十一)

1. 数据存储 1.1 知识点 &#xff08;1&#xff09;掌握Android数据存储的分类&#xff1b; &#xff08;2&#xff09;可以使用SharedPreferences存储数据。 1.2 具体内容 对于我们数据的存储而言&#xff0c;Android一共提供了5个数据存储的方式&#xff1a;SharedPrefe…

任天堂开发全新独立VR设备,或为下一代主机?将提供混合现实体验

根据爆料人Nash Weedle在X平台上的发文&#xff0c;我们得知任天堂正在秘密开发一款全新的独立VR设备&#xff0c;该设备将拥有一块MicroLED屏幕&#xff0c;并且独立于任天堂传闻中的下一代主机。与此同时&#xff0c;谷歌也参与了这款VR产品的研发工作。 这一新的VR设备被设计…