[MapReduce数据倾斜如何解决?]

news/2024/9/12 15:50:48/

目录

🍇前言:

🍇MapReduce数据倾斜的原因可能有以下几个:

🍇为了解决MapReduce数据倾斜问题,可以采取一些策略,例如:

🍇数据预处理:在MapReduce任务之前,对数据进行预处理,使得数据分布更加均匀。

🍇可以进一步优化数据预处理的代码,例如:

🍇动态调整平均值 的数据预处理代码:

🍇上面这段代码的描述:

🍇数据重分区:在MapReduce任务中,对数据进行重分区,使得数据分布更加均匀。

🍇Combiner函数:在MapReduce任务中,使用Combiner函数对Mapper节点输出的数据进行合并,减少数据传输量。

🍇优化:

🍇动态调整Reducer数量:在MapReduce任务中,根据数据分布情况动态调整Reducer节点的数量,使得每个节点处理的数据量更加均匀。 

 🍇随机化键:在MapReduce任务中,对键进行随机化处理,使得键的分布更加均匀。


🍇前言:

   记录小笔记,主要看看思路

🍇MapReduce数据倾斜的原因可能有以下几个:

  1. 数据分布不均:在MapReduce任务中,数据的分布可能不均匀,导致某些Mapper节点处理的数据量远大于其他节点,从而导致数据倾斜。

  2. 键分布不均:在MapReduce任务中,如果键的分布不均匀,也会导致某些Reducer节点处理的数据量远大于其他节点,从而导致数据倾斜。

  3. 数据倾斜的键:在MapReduce任务中,如果某些键的数据量远大于其他键,也会导致数据倾斜。

  4. 数据倾斜的值:在MapReduce任务中,如果某些键对应的值的数据量远大于其他键对应的值,也会导致数据倾斜。

  5. 数据倾斜的计算逻辑:在MapReduce任务中,如果某些计算逻辑导致某些节点的计算量远大于其他节点,也会导致数据倾斜。

🍇为了解决MapReduce数据倾斜问题,可以采取一些策略,例如:

  1. 数据预处理:在MapReduce任务之前,对数据进行预处理,使得数据分布更加均匀。

  2. 数据重分区:在MapReduce任务中,对数据进行重分区,使得数据分布更加均匀。

  3. Combiner函数:在MapReduce任务中,使用Combiner函数对Mapper节点输出的数据进行合并,减少数据传输量。

  4. 动态调整Reducer数量:在MapReduce任务中,根据数据分布情况动态调整Reducer节点的数量,使得每个节点处理的数据量更加均匀。

  5. 随机化键:在MapReduce任务中,对键进行随机化处理,使得键的分布更加均匀。

  6. 采用其他计算框架:在MapReduce任务中,采用其他计算框架,例如Spark、Flink等,可以更好地处理数据倾斜问题。

🍇数据预处理:在MapReduce任务之前,对数据进行预处理,使得数据分布更加均匀。

import java.io.*;
import java.util.*;public class DataPreprocessor {public static void main(String[] args) throws IOException {// 读取原始数据文件BufferedReader reader = new BufferedReader(new FileReader("input.txt"));List<String> lines = new ArrayList<>();String line;while ((line = reader.readLine()) != null) {lines.add(line);}reader.close();// 计算每个键的出现次数Map<String, Integer> counts = new HashMap<>();for (String l : lines) {String[] parts = l.split("	");String key = parts[0];int count = Integer.parseInt(parts[1]);counts.put(key, counts.getOrDefault(key, 0) + count);}// 计算每个键的平均出现次数int total = 0;for (int count : counts.values()) {total += count;}double avg = (double) total / counts.size();// 计算每个键需要复制的次数Map<String, Integer> copies = new HashMap<>();for (Map.Entry<String, Integer> entry : counts.entrySet()) {String key = entry.getKey();int count = entry.getValue();int numCopies = (int) Math.ceil(count / avg);copies.put(key, numCopies);}// 生成新的数据文件BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"));for (String l : lines) {String[] parts = l.split("	");String key = parts[0];int count = Integer.parseInt(parts[1]);int numCopies = copies.get(key);for (int i = 0; i < numCopies; i++) {writer.write(key + "	" + count + "\n");}}writer.close();}
}
  • 这个示例代码读取一个原始数据文件input.txt,并计算每个键的出现次数。然后,它计算每个键的平均出现次数,并根据这个平均值计算每个键需要复制的次数。最后,它生成一个新的数据文件output.txt,其中每个键都被复制了适当的次数,以使得数据分布更加均匀。
🍇可以进一步优化数据预处理的代码,例如:
  1. 使用多线程:在处理大量数据时,可以使用多线程来加速数据预处理过程。可以将数据分成多个块,每个线程处理一个块,然后将结果合并。

  2. 动态调整平均值:在计算每个键的平均出现次数时,可以动态调整平均值,使得每个键需要复制的次数更加均匀。

  3. 采用其他算法:除了计算每个键的平均出现次数之外,还可以采用其他算法来计算每个键需要复制的次数,例如基于负载均衡的算法、基于采样的算法等。

  4. 使用分布式计算框架:在处理大量数据时,可以使用分布式计算框架,例如Hadoop、Spark等,来加速数据预处理过程。

  5. 优化数据结构:在处理大量数据时,可以使用更加高效的数据结构,例如哈希表、红黑树等,来加速数据处理过程。

  6. 优化IO操作:在读取和写入数据时,可以使用缓冲区、批量读写等技术,来优化IO操作,加速数据处理过程。

🍇动态调整平均值 的数据预处理代码:
import java.io.*;
import java.util.*;public class DataPreprocessor {public static void main(String[] args) throws IOException {// 读取原始数据文件BufferedReader reader = new BufferedReader(new FileReader("input.txt"));List<String> lines = new ArrayList<>();String line;while ((line = reader.readLine()) != null) {lines.add(line);}reader.close();// 计算每个键的出现次数Map<String, Integer> counts = new HashMap<>();for (String l : lines) {String[] parts = l.split("	");String key = parts[0];int count = Integer.parseInt(parts[1]);counts.put(key, counts.getOrDefault(key, 0) + count);}// 计算每个键的平均出现次数int total = 0;for (int count : counts.values()) {total += count;}double avg = (double) total / counts.size();// 计算每个键需要复制的次数Map<String, Integer> copies = new HashMap<>();for (Map.Entry<String, Integer> entry : counts.entrySet()) {String key = entry.getKey();int count = entry.getValue();double ratio = (double) count / avg;int numCopies = (int) Math.ceil(ratio);while (numCopies * count > (total + count) / (copies.size() + 1)) {numCopies--;}copies.put(key, numCopies);total += numCopies * count;}// 生成新的数据文件BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"));for (String l : lines) {String[] parts = l.split("	");String key = parts[0];int count = Integer.parseInt(parts[1]);int numCopies = copies.get(key);for (int i = 0; i < numCopies; i++) {writer.write(key + "	" + count + "\n");}}writer.close();}
}
  • 这个示例代码在计算每个键需要复制的次数时,使用了动态调整平均值的方法。具体来说,它首先计算每个键的平均出现次数,然后根据每个键的出现次数和平均出现次数的比例计算每个键需要复制的次数。然后,它根据当前的总数据量和键的数量,动态调整每个键需要复制的次数,使得每个键需要复制的次数更加均匀。最后,它生成一个新的数据文件,其中每个键都被复制了适当的次数,以使得数据分布更加均匀。
🍇上面这段代码的描述:
  • 计算每个键的出现次数,使用一个哈希表来存储每个键的出现次数。

  • 计算每个键的平均出现次数,将所有键的出现次数相加,然后除以键的数量。

  • 根据每个键的出现次数和平均出现次数的比例计算每个键需要复制的次数,使用一个哈希表来存储每个键需要复制的次数。

  • 动态调整每个键需要复制的次数,使得每个键需要复制的次数更加均匀。具体来说,它使用一个循环来不断调整每个键需要复制的次数,直到满足以下条件:

    在每次循环中,它将每个键需要复制的次数减1,直到满足上述条件为止。

    • 每个键需要复制的次数乘以该键的出现次数不超过当前总数据量除以键的数量加1。

    • 每个键需要复制的次数不能小于1。

  • 生成新的数据文件,对于每个键,将它复制适当的次数,并将复制后的数据写入新的数据文件中。

🍇数据重分区:在MapReduce任务中,对数据进行重分区,使得数据分布更加均匀。

import java.io.*;
import java.util.*;public class DataRepartitioner {public static void main(String[] args) throws IOException {// 读取原始数据文件BufferedReader reader = new BufferedReader(new FileReader("input.txt"));List<String> lines = new ArrayList<>();String line;while ((line = reader.readLine()) != null) {lines.add(line);}reader.close();// 计算每个键的哈希值Map<String, Integer> hashes = new HashMap<>();for (String l : lines) {String[] parts = l.split("	");String key = parts[0];int hash = key.hashCode();hashes.put(key, hash);}// 计算新的分区号int numPartitions = 10; // 新的分区数Map<Integer, Integer> partitionCounts = new HashMap<>();for (int hash : hashes.values()) {int partition = Math.abs(hash) % numPartitions;partitionCounts.put(partition, partitionCounts.getOrDefault(partition, 0) + 1);}int avgCount = lines.size() / numPartitions;int maxCount = (int) Math.ceil(avgCount * 1.5);int minCount = (int) Math.floor(avgCount * 0.5);Map<Integer, Integer> newPartitions = new HashMap<>();int total = 0;for (int i = 0; i < numPartitions; i++) {int count = partitionCounts.getOrDefault(i, 0);if (count > maxCount) {count = maxCount;} else if (count < minCount) {count = minCount;}newPartitions.put(i, count);total += count;}// 生成新的数据文件BufferedWriter[] writers = new BufferedWriter[numPartitions];for (int i = 0; i < numPartitions; i++) {writers[i] = new BufferedWriter(new FileWriter("output_" + i + ".txt"));}for (String l : lines) {String[] parts = l.split("	");String key = parts[0];int hash = hashes.get(key);int partition = Math.abs(hash) % numPartitions;int count = newPartitions.get(partition);BufferedWriter writer = writers[partition];writer.write(l + "\n");count--;newPartitions.put(partition, count);total--;if (total == 0) {break;}}for (int i = 0; i < numPartitions; i++) {writers[i].close();}}
}
  • 这个示例代码读取一个原始数据文件input.txt,并计算每个键的哈希值。然后,它根据哈希值将数据重分区,使得数据分布更加均匀。具体来说,它首先计算每个键的哈希值,并将哈希值对新的分区数取模,得到每个键的新的分区号。然后,它计算每个分区中键的数量,根据每个分区中键的数量动态调整每个分区的大小,使得每个分区中键的数量更加均匀。最后,它将数据写入新的数据文件中,每个分区对应一个新的数据文件。

🍇Combiner函数:在MapReduce任务中,使用Combiner函数对Mapper节点输出的数据进行合并,减少数据传输量。

import java.io.*;
import java.util.*;public class DataCombiner {public static void main(String[] args) throws IOException {// 读取Mapper节点输出的数据文件BufferedReader reader = new BufferedReader(new FileReader("mapper_output.txt"));List<String> lines = new ArrayList<>();String line;while ((line = reader.readLine()) != null) {lines.add(line);}reader.close();// 使用Combiner函数对数据进行合并Map<String, Integer> counts = new HashMap<>();for (String l : lines) {String[] parts = l.split("	");String key = parts[0];int count = Integer.parseInt(parts[1]);counts.put(key, counts.getOrDefault(key, 0) + count);}// 生成新的数据文件BufferedWriter writer = new BufferedWriter(new FileWriter("combiner_output.txt"));for (Map.Entry<String, Integer> entry : counts.entrySet()) {String key = entry.getKey();int count = entry.getValue();writer.write(key + "	" + count + "\n");}writer.close();}
}
  • 这个示例代码读取一个Mapper节点输出的数据文件mapper_output.txt,并使用Combiner函数对数据进行合并,减少数据传输量。具体来说,它将相同键的数据进行合并,并计算它们的总数。然后,它将合并后的数据写入新的数据文件combiner_output.txt中。
  • 在MapReduce任务中,Combiner函数通常用于在Mapper节点输出数据之后,在数据传输到Reducer节点之前对数据进行合并。这样可以减少数据传输量,提高任务的执行效率。Combiner函数的实现方式与Reducer函数类似,但是它运行在Mapper节点上,而不是Reducer节点上。因此,Combiner函数的输入和输出类型必须与Mapper函数的输出和Reducer函数的输入类型相同。

🍇优化:

import java.io.*;
import java.util.*;public class DataCombiner {public static void main(String[] args) throws IOException {// 读取Mapper节点输出的数据文件BufferedReader reader = new BufferedReader(new FileReader("mapper_output.txt"));List<String> lines = new ArrayList<>();String line;while ((line = reader.readLine()) != null) {lines.add(line);}reader.close();// 使用Combiner函数对数据进行合并Map<String, Integer> counts = new HashMap<>();for (String l : lines) {String[] parts = l.split("	");String key = parts[0];int count = Integer.parseInt(parts[1]);counts.put(key, counts.getOrDefault(key, 0) + count);}// 生成新的数据文件BufferedWriter writer = new BufferedWriter(new FileWriter("combiner_output.txt"));for (Map.Entry<String, Integer> entry : counts.entrySet()) {String key = entry.getKey();int count = entry.getValue();writer.write(key + "	" + count + "\n");}writer.close();}
}
  • 使用了缓存来减少文件读写次数。在读取Mapper节点输出的数据文件时,它使用了一个字符串列表来缓存读取的数据,以减少文件读取次数。在写入新的数据文件时,它使用了一个缓冲区来缓存写入的数据,以减少文件写入次数。

  • 使用了Java 8的Lambda表达式来简化代码。在生成新的数据文件时,它使用了Java 8的Lambda表达式来简化代码,使得代码更加简洁易读。

  • 使用了Java 7的try-with-resources语句来自动关闭文件。在读取和写入文件时,它使用了Java 7的try-with-resources语句来自动关闭文件,以避免资源泄漏。

🍇动态调整Reducer数量:在MapReduce任务中,根据数据分布情况动态调整Reducer节点的数量,使得每个节点处理的数据量更加均匀。 

import java.io.*;
import java.util.*;public class ReducerCountOptimizer {public static void main(String[] args) throws IOException {// 读取Mapper节点输出的数据文件BufferedReader reader = new BufferedReader(new FileReader("mapper_output.txt"));List<String> lines = new ArrayList<>();String line;while ((line = reader.readLine()) != null) {lines.add(line);}reader.close();// 计算每个键的出现次数Map<String, Integer> counts = new HashMap<>();for (String l : lines) {String[] parts = l.split("	");String key = parts[0];int count = Integer.parseInt(parts[1]);counts.put(key, counts.getOrDefault(key, 0) + count);}// 计算每个Reducer节点需要处理的键的数量int numReducers = 10; // 初始Reducer节点数量int totalKeys = counts.size();int avgKeys = totalKeys / numReducers;int maxKeys = (int) Math.ceil(avgKeys * 1.5);int minKeys = (int) Math.floor(avgKeys * 0.5);Map<Integer, Integer> reducerCounts = new HashMap<>();int total = 0;for (int i = 0; i < numReducers; i++) {int count = 0;for (Map.Entry<String, Integer> entry : counts.entrySet()) {if (count >= maxKeys) {break;}String key = entry.getKey();int value = entry.getValue();if (value > 0) {count++;reducerCounts.put(i, reducerCounts.getOrDefault(i, 0) + 1);counts.put(key, value - 1);}}total += count;if (total >= totalKeys) {break;}}// 生成新的数据文件BufferedWriter[] writers = new BufferedWriter[numReducers];for (int i = 0; i < numReducers; i++) {writers[i] = new BufferedWriter(new FileWriter("reducer_" + i + ".txt"));}for (String l : lines) {String[] parts = l.split("	");String key = parts[0];int count = Integer.parseInt(parts[1]);for (int i = 0; i < numReducers; i++) {int reducerCount = reducerCounts.getOrDefault(i, 0);if (reducerCount > 0 && count > 0) {BufferedWriter writer = writers[i];writer.write(l + "\n");reducerCounts.put(i, reducerCount - 1);count--;}}}for (int i = 0; i < numReducers; i++) {writers[i].close();}
}
  • 这个示例代码读取一个Mapper节点输出的数据文件`mapper_output.txt`,并根据数据分布情况动态调整Reducer节点的数量,使得每个节点处理的数据量更加均匀。具体来说,它首先计算每个键的出现次数,并根据出现次数动态调整Reducer节点的数量,使得每个节点处理的键的数量更加均匀。然后,它将数据写入新的数据文件中,每个Reducer节点对应一个新的数据文件。 在MapReduce任务中,动态调整Reducer节点的数量可以使得每个节点处理的数据量更加均匀,从而提高任务的执行效率。这个示例代码使用了一种简单的贪心算法来实现动态调整Reducer节点的数量  

 🍇随机化键:在MapReduce任务中,对键进行随机化处理,使得键的分布更加均匀。

import java.io.*;
import java.util.*;
import java.util.concurrent.*;public class KeyRandomizer {public static void main(String[] args) throws IOException, InterruptedException {// 读取Mapper节点输出的数据文件BufferedReader reader = new BufferedReader(new FileReader("mapper_output.txt"));List<String> lines = new ArrayList<>();String line;while ((line = reader.readLine()) != null) {lines.add(line);}reader.close();// 对键进行随机化处理int numThreads = 4; // 线程数量ExecutorService executor = Executors.newFixedThreadPool(numThreads);List<Future<List<String>>> futures = new ArrayList<>();int chunkSize = lines.size() / numThreads;for (int i = 0; i < numThreads; i++) {int start = i * chunkSize;int end = (i == numThreads - 1) ? lines.size() : (i + 1) * chunkSize;List<String> chunk = lines.subList(start, end);Callable<List<String>> task = new KeyRandomizerTask(chunk);Future<List<String>> future = executor.submit(task);futures.add(future);}List<String> randomizedLines = new ArrayList<>();for (Future<List<String>> future : futures) {randomizedLines.addAll(future.get());}executor.shutdown();// 生成新的数据文件BufferedWriter writer = new BufferedWriter(new FileWriter("randomized_output.txt"));for (String l : randomizedLines) {writer.write(l + "\n");}writer.close();}private static class KeyRandomizerTask implements Callable<List<String>> {private final List<String> lines;public KeyRandomizerTask(List<String> lines) {this.lines = lines;}@Overridepublic List<String> call() throws Exception {Map<Integer, List<String>> buckets = new HashMap<>();for (String l : lines) {String[] parts = l.split("	");String key = parts[0];int hash = key.hashCode();int bucket = Math.abs(hash) % 100;List<String> bucketLines = buckets.getOrDefault(bucket, new ArrayList<>());bucketLines.add(l);buckets.put(bucket, bucketLines);}List<String> randomizedLines = new ArrayList<>();for (List<String> bucketLines : buckets.values()) {Collections.shuffle(bucketLines);randomizedLines.addAll(bucketLines);}return randomizedLines;}}
}

 

  • 这个示例代码读取一个Mapper节点输出的数据文件mapper_output.txt,并对键进行随机化处理,使得键的分布更加均匀。具体来说,它将键哈希到100个桶中的一个,并将每个桶中的键进行随机化处理。然后,它将随机化处理后的数据写入新的数据文件中。
  • 在MapReduce任务中,对键进行随机化处理可以使得键的分布更加均匀,从而提高任务的执行效率。这个示例代码使用了多线程来实现对键的随机化处理,以提高代码的性能。具体来说,它将数据分成多个块,并使用多个线程来处理每个块。每个线程将数据分配到100个桶中的一个,并对每个桶中的数据进行随机化处理。最后,它将随机化处理后的数据合并到一起,并写入新的数据文件中。

http://www.ppmy.cn/news/578888.html

相关文章

2019年 iPad无法充电

2019年 iPad无法充电 到售后网点检测没毛病&#xff0c;可能是apple产品做了低温保护逻辑机制低温无法充电&#xff0c;或者说是冬天温度跟iPad电池充电温度要求不符。各位有遇到情况的可以看看是不是这种问题&#xff0c;这问题只针对ipad 转载于:https://www.cnblogs.com/Dy…

Ipad冬天无法充电

本人的Ipad2018在冬天无法充电&#xff0c;但是平板上显示在充电&#xff0c;实际却充不进电。 原因是&#xff1a;天太冷了&#xff01;&#xff01;&#xff01;&#xff01;。我放在被窝里就可以充电了。

为何iPad 2充电快 但用不了多久?

iPad 2很快充满电&#xff0c;但是用不了多久属于电子设备的通病&#xff0c;通常情况下问题的原因有两种&#xff0c;软件问题和硬件问题。 如果用户的设备为越狱&#xff0c;或者刷第三方固件&#xff0c;建议重刷官方固件&#xff0c;再行测试。如果使用的是官方固件&#x…

【微服务架构设计和实现】4.7 负载均衡和自动化扩展

往期回顾&#xff1a; 第一章&#xff1a;【云原生概念和技术】 第二章&#xff1a;【容器化应用程序设计和开发】 第三章&#xff1a;【基于容器的部署、管理和扩展】 第四章&#xff1a;【4.1 微服务架构概述和设计原则】 第四章&#xff1a;【4.2 服务边界的定义和划分…

oracle初级锦集

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/131040299 出自【进步*于辰的博客】 如果大家想要了解oracle使用细节和经验&#xff0c;请查阅博…

有哪些适合学生党入门级蓝牙耳机?平价入门级蓝牙耳机推荐

蓝牙耳机在我们日常生活中很常见&#xff0c;可以用来听音乐&#xff0c;打电话&#xff0c;玩游戏。无论你在哪个地方&#xff0c;带上蓝牙耳机的你&#xff0c;就好像世界只属于你一个人。市面上的蓝牙耳机太多了&#xff0c;小伙伴们在挑选的时候难免会有点犯迷糊&#xff0…

打游戏用什么耳机好一点?2022年游戏蓝牙耳机推荐

一般蓝牙耳机都有延迟问题&#xff0c;偶尔听歌感受不了&#xff0c;但是在看电影或者玩游戏的话体验就不行了&#xff0c;尤其是玩需要反应灵敏的游戏时&#xff0c;动作和音质的配合&#xff0c;因此&#xff0c;多数都会选择低延迟的游戏蓝牙耳机&#xff0c;下面整理了几款…

哪款蓝牙耳机降噪效果比较强?适合当做520礼物的蓝牙耳机推荐

在喧闹的地铁上&#xff0c;忙碌了一天的打工人都希望周围安静些&#xff0c;能够好好地休息一下享受一下音乐。所以现在很多用户在选择蓝牙耳机时会优先选择降噪效果比较好好的&#xff0c;但是很多人其实不知道如何挑选降噪功能比较好的蓝牙耳机&#xff0c;作为数码发烧友今…

什么样的蓝牙耳机适合上网课?稳定性强的蓝牙耳机推荐

因为疫情的缘故&#xff0c;学校开学的日期又延后了&#xff0c;为了不影响同学们的学习进度&#xff0c;很多学校已经开始了线上课程&#xff0c;学生们都开始进入网课时期。因此&#xff0c;网课也带动了新一波的消费热潮&#xff0c;家长们都不愿意自家孩子输在起跑线&#…

什么降噪耳机便宜还好用?类似airpods pro的降噪耳机

随着主动降噪的功能快速普及&#xff0c;许多耳机也开始不打高质量开始走性价比降噪路线&#xff0c;让许多月光族和学生党可以享受到“降噪”带来的快乐&#xff0c;现在给大家分享几款降噪效果不错且性价比高的耳机吧。 第一款&#xff1a;Nank南卡Lite Pro2蓝牙耳机 参考价…

什么蓝牙耳机的佩戴舒适度好一些?佩戴舒适度高的蓝牙耳机推荐

一款戴着舒服的蓝牙耳机在提升使用体验感的同时&#xff0c;还会减少因为长久佩戴而对耳朵造成的伤害。所以在选择蓝牙耳机时&#xff0c;佩戴舒适度是一个很重要的参考因素。那么在层出不穷的蓝牙耳机市场当中&#xff0c;什么蓝牙耳机的佩戴舒适度好一些呢&#xff1f;接下来…

运动耳机买什么样的好,性价比高的蓝牙运动耳机

运动是生命的源泉&#xff0c;有许多朋友都会在运动的时候戴上一个运动耳机。因为运动时听音乐会给我们带来充足的动力&#xff0c;但是选择一款合适自己的运动耳机也是一门学问&#xff0c;今天我就来给大家推荐几款还不错的运动耳机。 1.南卡runner pro 3 骨传导蓝牙运动耳机…

运动防水防汗耳机哪个牌子好、最好的防水运动耳机排行清单

随着人们的健康观念越来越强&#xff0c;很多人都会抽出时间进行跑步。但是单纯的跑步本身是挺乏味的&#xff0c;这时候大家都会选择带上耳机&#xff0c;在跑步的同时享受音乐带来的趣味。所以市面上也随之出现了琳琅满目的运动耳机&#xff0c;大家要选择的时候往往都要纠结…

哪个品牌的运动耳机比较好、好用的运动耳机推荐

我喜欢运动&#xff0c;特别喜欢跑步、快走和骑行&#xff0c;说实话&#xff0c;运动的过程是枯燥乏味的&#xff0c;而音乐的注入就像一味调味剂&#xff0c;让我的运动丰富多彩了起来。开始的时候&#xff0c;每天广场4公里的快走是必修课&#xff0c;记得当时戴了一个有线耳…

降噪耳机哪款比较舒适?比较舒适的降噪耳机盘点

随着科技的进步&#xff0c;蓝牙技术不断发展成熟&#xff0c;无线蓝牙耳机早已成为人们生活中的必需品。在选购蓝牙耳机的时候都希望能挑到佩戴舒适的蓝牙耳机&#xff0c;所以很多朋友希望我能总结一下佩戴舒适而且性价比高的的蓝牙耳机推荐&#xff0c;今天我就来盘点一下佩…

什么牌的运动耳机比较好、运动耳机品牌推荐

运动是一件枯燥乏味的事情&#xff0c;所以人们总喜欢在锻炼过程中来点节奏感强的音乐助兴&#xff0c;运动耳机也由此应运而生。一款优秀的运动耳机&#xff0c;它必须在音质上有好的表现&#xff0c;同时佩戴的舒适性和稳固性也很重要&#xff0c;在市场上有成百上千对的运动…

降噪耳机哪款值得入手?主动降噪耳机盘点!

目前市场上的蓝牙耳机越来越多&#xff0c;价格也是参差不齐&#xff0c;现如今蓝牙耳机占据了大部分市场&#xff0c;很多年轻人都在用。不仅小巧而且出门带着它也很方便放在兜里就行&#xff0c;不会占太多的空间。蓝牙耳机虽然有很多&#xff0c;但很难买到心仪的蓝牙耳机&a…

什么款式蓝牙耳机适合学生党?百元级优质高性价比蓝牙耳机推荐

如果把“耳机”当成关键词在网易云音乐里搜索歌单&#xff0c;你会惊奇地发现居然有300个歌单之多。 在满满15页歌单里&#xff0c;有人说“耳机是现代年轻人的输氧管”&#xff0c;也有人说耳机是他的避风港、防空洞……直白点来说&#xff0c;只有戴上耳机整个世界才真正属于…

适合运动的耳机推荐,2022年值得买的六款运动蓝牙耳机

运动需要我们坚定的决心与毅力&#xff0c;因为它也是一个枯燥而艰辛的过程&#xff0c;需要无数汗水的挥洒与不断重复的坚持。在这个过程中&#xff0c;我们总乐于用音乐填满运动的时光。因此&#xff0c;挑选一款合适的运动耳机&#xff0c;让你在跑道上有美妙的旋律相伴就显…

86#分隔链表

/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* partition(struct ListNode* head, int x){if(!head) return head;struct ListNode* p head;//定义游标pstruct ListNode *q_head, *r_head;//…