开启你的编程学习之旅

云课堂提供高质量的编程课程,从入门到精通,助你成为技术大牛

立即开始学习

Java 编程入门

作者: 赵老师 更新: 2024-03-18 阅读: 51234 难度: 初级
学习工具

8. Java URL数据处理与StringBuffer/StringBuilder

Java 提供了强大的网络编程能力和字符串处理工具,包括URL数据处理、StringBuffer和StringBuilder类,这些在处理网络请求和字符串操作时非常有用。

URL 数据处理基础

Java 中可以使用 URL 和 HttpURLConnection 类进行网络请求:

基本的URL连接示例
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class URLBasicExample { public static String fetchDataFromURL(String urlString) throws IOException { StringBuilder result = new StringBuilder(); HttpURLConnection connection = null; BufferedReader reader = null; try { // 创建URL对象 URL url = new URL(urlString); // 打开连接 connection = (HttpURLConnection) url.openConnection(); // 设置请求方法 connection.setRequestMethod("GET"); // 设置超时时间 connection.setConnectTimeout(5000); connection.setReadTimeout(5000); // 设置请求头 connection.setRequestProperty("User-Agent", "Mozilla/5.0"); connection.setRequestProperty("Accept", "application/json"); // 获取响应码 int responseCode = connection.getResponseCode(); System.out.println("响应码: " + responseCode); if (responseCode == HttpURLConnection.HTTP_OK) { // 读取响应数据 reader = new BufferedReader( new InputStreamReader(connection.getInputStream())); String line; while ((line = reader.readLine()) != null) { result.append(line); result.append("\n"); } } else { System.out.println("请求失败,响应码: " + responseCode); } } finally { // 关闭资源 if (reader != null) { reader.close(); } if (connection != null) { connection.disconnect(); } } return result.toString(); } public static void main(String[] args) { try { String url = "https://jsonplaceholder.typicode.com/posts/1"; String response = fetchDataFromURL(url); System.out.println("获取的数据:"); System.out.println(response); } catch (IOException e) { e.printStackTrace(); } } }

StringBuffer 类详解

StringBuffer 是线程安全的可变字符串类:

StringBuffer 示例
public class StringBufferExample { public static void main(String[] args) { // 1. 创建 StringBuffer 对象 StringBuffer sb1 = new StringBuffer(); // 默认容量16 StringBuffer sb2 = new StringBuffer(50); // 指定初始容量 StringBuffer sb3 = new StringBuffer("Hello"); // 指定初始字符串 System.out.println("初始字符串: " + sb3); System.out.println("初始容量: " + sb3.capacity()); System.out.println("当前长度: " + sb3.length()); // 2. 追加操作 sb3.append(" World"); sb3.append("!"); System.out.println("追加后: " + sb3); // 3. 插入操作 sb3.insert(5, " Beautiful"); System.out.println("插入后: " + sb3); // 4. 删除操作 sb3.delete(5, 15); // 删除 " Beautiful" System.out.println("删除后: " + sb3); // 5. 替换操作 sb3.replace(6, 11, "Java"); System.out.println("替换后: " + sb3); // 6. 反转操作 sb3.reverse(); System.out.println("反转后: " + sb3); sb3.reverse(); // 恢复原状 // 7. 设置字符和获取字符 sb3.setCharAt(0, 'h'); System.out.println("修改首字符后: " + sb3); System.out.println("第1个字符: " + sb3.charAt(0)); // 8. 子字符串操作 System.out.println("子字符串(0,5): " + sb3.substring(0, 5)); // 9. 容量管理 System.out.println("当前容量: " + sb3.capacity()); sb3.ensureCapacity(100); // 确保最小容量 System.out.println("确保容量后: " + sb3.capacity()); // 10. 性能测试 - 大量字符串拼接 StringBuffer performanceTest = new StringBuffer(); long startTime = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { performanceTest.append("Number ").append(i).append(", "); } long endTime = System.currentTimeMillis(); System.out.println("StringBuffer 拼接10000次耗时: " + (endTime - startTime) + "ms"); // 11. 线程安全演示 System.out.println("\n=== 线程安全测试 ==="); StringBuffer threadSafeBuffer = new StringBuffer(); Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { threadSafeBuffer.append("A"); } }); Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) { threadSafeBuffer.append("B"); } }); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程安全测试完成,长度: " + threadSafeBuffer.length()); } }

StringBuilder 类详解

StringBuilder 是非线程安全的可变字符串类,性能更高:

StringBuilder 示例
public class StringBuilderExample { public static void main(String[] args) { // 1. 创建 StringBuilder 对象 StringBuilder sb1 = new StringBuilder(); StringBuilder sb2 = new StringBuilder(50); StringBuilder sb3 = new StringBuilder("Hello"); System.out.println("初始字符串: " + sb3); // 2. 链式操作 sb3.append(" World") .append("!") .insert(5, " Amazing") .delete(5, 13); System.out.println("链式操作后: " + sb3); // 3. 性能测试 - 与 StringBuffer 对比 int iterations = 100000; // StringBuilder 性能测试 StringBuilder sbPerformance = new StringBuilder(); long startTime1 = System.currentTimeMillis(); for (int i = 0; i < iterations; i++) { sbPerformance.append("test"); } long endTime1 = System.currentTimeMillis(); System.out.println("StringBuilder 拼接" + iterations + "次耗时: " + (endTime1 - startTime1) + "ms"); // StringBuffer 性能测试 StringBuffer sbufPerformance = new StringBuffer(); long startTime2 = System.currentTimeMillis(); for (int i = 0; i < iterations; i++) { sbufPerformance.append("test"); } long endTime2 = System.currentTimeMillis(); System.out.println("StringBuffer 拼接" + iterations + "次耗时: " + (endTime2 - startTime2) + "ms"); // 4. 复杂字符串构建 StringBuilder complexBuilder = new StringBuilder(); // 构建表格数据 complexBuilder.append("=== 学生信息表 ===\n"); complexBuilder.append(String.format("%-10s %-8s %-6s\n", "姓名", "年龄", "成绩")); complexBuilder.append("------------------------\n"); String[][] students = { {"张三", "20", "85"}, {"李四", "19", "92"}, {"王五", "21", "78"} }; for (String[] student : students) { complexBuilder.append(String.format("%-10s %-8s %-6s\n", student[0], student[1], student[2])); } System.out.println("\n构建的表格:"); System.out.println(complexBuilder.toString()); // 5. 字符串处理工具方法 System.out.println("\n=== 字符串处理工具 ==="); String processed = processString(" Hello, World! "); System.out.println("处理后的字符串: " + processed + ); } // 字符串处理工具方法 public static String processString(String input) { StringBuilder sb = new StringBuilder(input); // 去除首尾空格 while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) { sb.deleteCharAt(0); } while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) { sb.deleteCharAt(sb.length() - 1); } // 转换为大写 for (int i = 0; i < sb.length(); i++) { char c = sb.charAt(i); if (Character.isLowerCase(c)) { sb.setCharAt(i, Character.toUpperCase(c)); } } return sb.toString(); } }

综合应用:URL数据处理工具

结合URL处理和字符串构建的实际应用:

URL数据处理工具
import java.io.*; import java.net.*; import java.util.*; public class URLDataProcessor { // 获取URL内容并处理 public static String processURLData(String urlString) throws IOException { StringBuilder result = new StringBuilder(); HttpURLConnection connection = null; BufferedReader reader = null; try { URL url = new URL(urlString); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(10000); connection.setReadTimeout(10000); connection.setRequestProperty("User-Agent", "Java-URL-Processor"); int responseCode = connection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; int lineCount = 0; while ((line = reader.readLine()) != null && lineCount < 100) { // 处理每一行数据 String processedLine = processLine(line, lineCount + 1); result.append(processedLine).append("\n"); lineCount++; } if (line != null) { result.append("... (数据截断,只显示前100行)\n"); } } else { result.append("请求失败,响应码: ").append(responseCode); } } finally { if (reader != null) reader.close(); if (connection != null) connection.disconnect(); } return result.toString(); } // 处理单行数据 private static String processLine(String line, int lineNumber) { StringBuilder processed = new StringBuilder(); // 添加行号 processed.append(String.format("[%03d] ", lineNumber)); // 去除首尾空白 String trimmed = line.trim(); // 如果行太长,进行截断 if (trimmed.length() > 100) { processed.append(trimmed.substring(0, 97)).append("..."); } else { processed.append(trimmed); } // 统计信息(在行末添加) processed.append(" [长度:").append(trimmed.length()).append("]"); return processed.toString(); } // 构建URL参数 public static String buildURLWithParams(String baseURL, Map params) { StringBuilder urlBuilder = new StringBuilder(baseURL); if (params != null && !params.isEmpty()) { urlBuilder.append("?"); boolean firstParam = true; for (Map.Entry entry : params.entrySet()) { if (!firstParam) { urlBuilder.append("&"); } try { // URL编码参数 String encodedKey = URLEncoder.encode(entry.getKey(), "UTF-8"); String encodedValue = URLEncoder.encode(entry.getValue(), "UTF-8"); urlBuilder.append(encodedKey).append("=").append(encodedValue); firstParam = false; } catch (UnsupportedEncodingException e) { System.err.println("URL编码错误: " + e.getMessage()); } } } return urlBuilder.toString(); } // 解析URL参数 public static Map parseURLParams(String urlString) { Map params = new HashMap<>(); try { URL url = new URL(urlString); String query = url.getQuery(); if (query != null) { String[] pairs = query.split("&"); for (String pair : pairs) { int idx = pair.indexOf("="); if (idx > 0) { String key = URLDecoder.decode(pair.substring(0, idx), "UTF-8"); String value = URLDecoder.decode(pair.substring(idx + 1), "UTF-8"); params.put(key, value); } } } } catch (Exception e) { System.err.println("解析URL参数错误: " + e.getMessage()); } return params; } public static void main(String[] args) { try { // 测试URL构建 Map params = new HashMap<>(); params.put("q", "java programming"); params.put("page", "1"); params.put("sort", "relevance"); String testURL = buildURLWithParams("https://api.example.com/search", params); System.out.println("构建的URL: " + testURL); // 测试URL参数解析 Map parsedParams = parseURLParams(testURL); System.out.println("解析的参数: " + parsedParams); // 测试URL数据处理(使用公开的测试API) String apiURL = "https://jsonplaceholder.typicode.com/posts"; String processedData = processURLData(apiURL); System.out.println("\n处理后的数据:"); System.out.println(processedData); } catch (IOException e) { e.printStackTrace(); } } }

StringBuffer vs StringBuilder 对比

性能对比测试
public class StringBufferVsStringBuilder { public static void main(String[] args) { final int ITERATIONS = 100000; // 单线程性能测试 System.out.println("=== 单线程性能测试 ==="); // StringBuilder 测试 long startTime = System.nanoTime(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < ITERATIONS; i++) { sb.append("test"); } long sbTime = System.nanoTime() - startTime; // StringBuffer 测试 startTime = System.nanoTime(); StringBuffer sbf = new StringBuffer(); for (int i = 0; i < ITERATIONS; i++) { sbf.append("test"); } long sbfTime = System.nanoTime() - startTime; System.out.println("StringBuilder 耗时: " + sbTime + " ns"); System.out.println("StringBuffer 耗时: " + sbfTime + " ns"); System.out.println("StringBuilder 比 StringBuffer 快: " + ((double)(sbfTime - sbTime) / sbfTime * 100) + "%"); // 多线程安全性测试 System.out.println("\n=== 多线程安全性测试 ==="); // StringBuilder 多线程测试(可能产生不一致结果) StringBuilder unsafeBuilder = new StringBuilder(); Thread t1 = new Thread(() -> appendMany(unsafeBuilder, "A", 1000)); Thread t2 = new Thread(() -> appendMany(unsafeBuilder, "B", 1000)); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("StringBuilder 最终长度: " + unsafeBuilder.length()); // StringBuffer 多线程测试(线程安全) StringBuffer safeBuffer = new StringBuffer(); Thread t3 = new Thread(() -> appendMany(safeBuffer, "A", 1000)); Thread t4 = new Thread(() -> appendMany(safeBuffer, "B", 1000)); t3.start(); t4.start(); try { t3.join(); t4.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("StringBuffer 最终长度: " + safeBuffer.length()); } private static void appendMany(Appendable appender, String str, int count) { for (int i = 0; i < count; i++) { try { appender.append(str); } catch (IOException e) { e.printStackTrace(); } } } }

关键知识点总结

  • URL 连接:使用 HttpURLConnection 进行网络请求,设置超时和请求头
  • StringBuffer:线程安全的可变字符串,适合多线程环境
  • StringBuilder:非线程安全的可变字符串,单线程环境下性能更好
  • 字符串操作:append、insert、delete、replace、reverse 等方法
  • 性能考虑:大量字符串操作时使用 StringBuilder/StringBuffer 而不是 String
  • URL 编码:使用 URLEncoder/URLDecoder 处理URL参数

最佳实践

  1. 单线程环境下优先使用 StringBuilder
  2. 多线程环境下使用 StringBuffer
  3. 大量字符串拼接时避免使用 String 的 + 操作符
  4. 网络请求时设置合理的超时时间
  5. 及时关闭网络连接和流资源
  6. 对URL参数进行编码以防止特殊字符问题

注意:在实际项目中,对于复杂的网络请求,建议使用更高级的HTTP客户端库如 Apache HttpClient 或 OkHttp,它们提供了更好的功能和错误处理机制。

提示: 这是一个重要的概念,需要特别注意理解和掌握。
注意: 这是一个常见的错误点,请避免犯同样的错误。