首页 文章 精选 留言 我的

精选列表

搜索[提高],共10000篇文章
优秀的个人博客,低调大师

🤞 .NET 框架 Furion v4.8.8.33 发布,稳定性大大提高

项目信息 Gitee:https://gitee.com/dotnetchina/Furion Github:https://github.com/MonkSoul/Furion 文档:http://furion.baiqian.ltd/ 本期更新 更新日志:http://furion.baiqian.ltd/docs/upgrade/ 新特性 [新增] 定时任务作业计划 OnChanged 事件处理 4.8.8.29 ⏱️2023.06.25 e4c4cf1 [新增] Swagger 分组信息可在任意配置文件中通过 [openapi:分组名] 进行配置 4.8.8.26 ⏱️2023.06.20 a70eed3 [新增] TP.WrapperRectangle 绘制矩形日志模板 4.8.8.25 ⏱️2023.06.14 60ffd76 [新增] IServiceScope.CreateDefaultHttpContext 拓展方法 4.8.8.24 ⏱️2023.06.07 11a55e1 [新增] 配置模块 IgnoreConfigurationFiles 支持完整的文件通配符 4.8.8.22 ⏱️2023.05.25 #I78ABL [新增] 定时任务支持二级虚拟目录 VisualPath 配置部署 4.8.8.20 ⏱️2023.05.18 #I740IA [新增] 监听日志 LoggingMonitor 支持 Razor Pages 4.8.8.16 ⏱️2023.05.15 #I7332C [新增] 定时任务作业处理程序工厂 IJobFactory 支持 4.8.8.13 ⏱️2023.05.08 ad58dd3 [新增] AES 支持对文件(含超大文件)进行加解密 4.8.8.11 ⏱️2023.05.05 1d2265b [新增] 动态 WebAPI 支持 text/plain 格式的 Body 参数 4.8.8.9 ⏱️2023.05.04 b49fe50 [新增] 插件化 IDynamicApiRuntimeChangeProvider 接口,可在运行时动态添加 WebAPI/Controller 4.8.8.8 ⏱️2023.05.04 322ea59 [新增] 定时任务 Schedular.CompileCSharpClassCode(code) 支持动态编译作业处理程序代码 4.8.8.7 ⏱️2023.04.30 fe1e8a1 [新增] App.CompileCSharpClassCode(code) 动态编译类定义代码 4.8.8.7 ⏱️2023.04.30 fe1e8a1 [新增] 粘土对象支持结构 struct 对象类型 4.8.8.7 ⏱️2023.04.30 a0fa3aa [新增] 定时任务支持配置 IJob 执行异常 FallbackAsync 回退策略 4.8.8.6 ⏱️2023.04.25 7671489 [新增] 定时任务支持在非 IOC/DI 项目类型中使用 4.8.8.5 ⏱️2023.04.24 #I6YJNB [新增] RSA 支持对超长字符(超 245 位)进行分段加解密 4.8.8.2 ⏱️2023.04.19 !788 感谢 @YaChengMu [新增] System.Text.Json 和 Newtonsoft.Json 对粘土对象 Clay 支持 4.8.8.1 ⏱️2023.04.18 #I6WKRZ [新增] 粘土对象可反射转换成特定 IEnumerable<T> 类型:clay.ConvertTo<T>() 4.8.8 ⏱️2023.04.13 5d54a65 [新增] Serve.IdleHost 支持返回 http 和 https 协议 Web 地址(端口) 4.8.8 ⏱️2023.04.13 fdf7885 突破性变化 [移除] 定时任务看板 SyncRate 配置,前后端采用最新的 SSE 推送技术替代 4.8.8.29 ⏱️2023.06.25 e4c4cf1 [调整] 监听日志 WriteFilter 和 ConfigureLogger 的 ActionExecutingContext 和 ActionExecutedContext 类型为 FilterContext 4.8.8.16 ⏱️2023.05.15 #I7332C [调整] IJsonSerializerProvider 序列化接口,添加 Deserialize 反序列化方法 4.8.8.15 ⏱️2023.05.15 !815 感谢 @YaChengMu 问题修复 [修复] 审计日志解析 DateTime 类型参数不是本地时间问题 4.8.8.33 ⏱️2023.06.29 #I7GW32 [修复] 定时任务因上一版本修改 4e2615b 导致 Cron 解析异常问题 4.8.8.32 ⏱️2023.06.28 #I7GQ5I [修复] 定时任务设置额外数据不支持 long/int64 类型参数问题 4.8.8.31 ⏱️2023.06.28 4e2615b [修复] 定时任务休眠毫秒数大于 int.MaxValue 时出现 ArgumentOutOfRangeException 4.8.8.27 ⏱️2023.06.21 #I7F6ZT [修复] Cron 表达式步长解析器错误 4.8.8.25 ⏱️2023.06.14 #I7D9XU [修复] 修复 ExpandoObject.ToDictionary() 转换异常 4.8.8.25 ⏱️2023.06.14 #I7BY0P [修复] 配置友好异常 FriendlyExceptionSettings:DefaultErrorMessage 无效问题 4.8.8.23 ⏱️2023.05.31 #I79LIG [修复] Swagger 进行分组后 Tags 不能进行分组过滤问题 4.8.8.22 ⏱️2023.05.25 #I78A55 [修复] 因 9d8cb82 代码提交导致命名服务解析异常问题 4.8.8.21 ⏱️2023.05.18 #I76JZR [修复] 因 9d8cb82 代码提交导致服务 AOP 异常拦截问题 4.8.8.17 ⏱️2023.05.15 #I73A8E [修复] 动态 WebAPI 自定义路由模板参数和自动拼接参数冲突问题 4.8.8.15 ⏱️2023.05.15 #I72ZZ2 [修复] 远程请求在被请求端返回非 200 状态码但实际请求已处理也抛异常问题 4.8.8.14 ⏱️2023.05.12 b14a51f [修复] App.CompileCSharpClassCode(code) 运行时添加匿名程序集编译异常问题 4.8.8.8 ⏱️2023.05.04 322ea59 [修复] LoggingMonitor 打印泛型类型如果存在多个泛型参数问题 4.8.8.8 ⏱️2023.05.04 8d9cb74 [修复] 脱敏处理如果字典存在重复词导致异常问题 4.8.8.4 ⏱️2023.04.23 #I6Y19K [修复] 远程请求 Body 参数为粘土对象 Clay 类型序列化有误 4.8.8.1 ⏱️2023.04.18 #I6WKRZ [修复] Serve.IdleHost 获取随机端口的本地地址带 $ 符号问题 4.8.8 ⏱️2023.04.13 ed6f292 其他更改 [调整] 规范化文档默认 Title 解析规则,不再自动添加空格 4.8.8.26 ⏱️2023.06.20 24b7a47 [调整] 组件 Component 模式支持 [DependsOn] 支持继承 4.8.8.16 ⏱️2023.05.15 #I733RF [调整] 定时任务 GC 回收逻辑,避免高频添加作业导致 尾延迟 问题 4.8.8.3 ⏱️2023.04.21 #I6XIV8 [调整] 定时任务日志设计,减少不必要的日志输出 4.8.8.3 ⏱️2023.04.21 #I6XI2L 文档 [新增] Jwt 身份验证过程监听文档 [新增] 事件总线 Redis 集成文档 [更新] 粘土对象文档、虚拟文件系统文档、序列化文档、事件总线文档、远程请求文档、数据加密文档、安全授权文档、动态 WebAPI 文档、定时任务文档、JSON 序列化文档、App 静态类文档、规范化文档、配置文档 贡献者 zetaluoxin (@zetaluoxin) !834 SongXinXin (@goodsxx) !832 !833 阿炬 (@quejuwen) !813 KaneLeung (@KaneLeung) !808 蒋状先生 (@JiangZhuangXianSheng) !806 NeoLu (@neolu) !804 蓝色天空 (@lds2013) !796 YaChengMu (@YaChengMu) !788 !815

优秀的个人博客,低调大师

PyTorch 1.5 发布,C++ 前端重大更新、引入新存储格式提高性能

PyTorch 1.5 发布了,此版本包括新增加了几个主要的API 和一些改进、对 C++ 前端有重大更新、用于计算机视觉模型的“通道维持(channels last)”存储格式,以及用于模型并行训练的分布式 RPC 框架的稳定版本。 同时,此版本还提供了针对 hessian 和 jacobian 的 autograd 的新 API,以及一个受 pybind 启发的允许创建 Custom C++ Class(定制类)的 API。 C++ FRONTEND API (STABLE) 之前被标记为实验性质的C++ 前端 API 现在已经与 Python 地位相当,并且总体特性已移至“稳定”状态。一些主要亮点包括: 现在覆盖率达到约 100%,并提供有关 C++ torch::nn 模块/函数的文档,开发者可以轻松地将其模型从 Python API 转换为 C++ API。 C++ 中的优化器与 Python 中的有所不同:C++ 优化器不能将参数组作为输入,而 Python 可以。此外,步骤函数的实现也不完全相同。在 1.5 版本中,C++ 优化器的行为将始终与 Python 等效器相同。 C++ 中缺少张量多维度索引 API 是一个众所周知的问题,并在 PyTorch GitHub issue 跟踪器和论坛中引起了很多讨论。以前的解决方法是结合使用 arrow/select/index_select/masked_select,与 Python API 的优雅张量 [:, 0, ..., mask] 语法相比,它比较笨拙且容易出错。在 1.5 版本中,开发者可以使用 tensor.index({Slice(), 0, “...”, mask}) 达到相同的目的。 ‘CHANNELS LAST’ MEMORY FORMAT FOR COMPUTER VISION MODELS (EXPERIMENTAL) 用于计算机视觉模型的“通道维持(channels last)”存储格式,目前处于实验阶段。该格式的内存布局可以充分发挥性能高效的卷积算法和硬件(NVIDIA 的 Tensor Core、FBGEMM、QNNPACK)的能力。此外,它被设计为通过运算符自动传播,从而允许在内存布局之间轻松切换。 CUSTOM C++ CLASSES (EXPERIMENTAL) 此版本添加了一个新的 API torch.CutomClassHolder,用于将自定义 C++ 类同时绑定到 TorchScript 和 Python,该 API 的语法与 pybind11 几乎相同。它允许开发者向 TorchScript 类型系统和运行时系统暴露其 C++ 类及其方法,以便他们可以实例化和操作 TorchScript/Python 中的任意 C++ 对象。C++ 绑定示例: template <class T> struct MyStackClass : torch::CustomClassHolder { std::vector<T> stack_; MyStackClass(std::vector<T> init) : stack_(std::move(init)) {} void push(T x) { stack_.push_back(x); } T pop() { auto val = stack_.back(); stack_.pop_back(); return val; } }; static auto testStack = torch::class_<MyStackClass<std::string>>("myclasses", "MyStackClass") .def(torch::init<std::vector<std::string>>()) .def("push", &MyStackClass<std::string>::push) .def("pop", &MyStackClass<std::string>::pop) .def("size", [](const c10::intrusive_ptr<MyStackClass>& self) { return self->stack_.size(); }); 它暴露了可以在 Python 和 TorchScript 中使用的类,如下所示: @torch.jit.script def do_stacks(s : torch.classes.myclasses.MyStackClass): s2 = torch.classes.myclasses.MyStackClass(["hi", "mom"]) print(s2.pop()) # "mom" s2.push("foobar") return s2 # ["hi", "foobar"] DISTRIBUTED RPC FRAMEWORK APIS (NOW STABLE) 分布式 RPC 框架在 1.4 版本中以实验性形式出现,现在它已经处于稳定状态。此过程涉及许多增强功能和 bug 修复,以使分布式 RPC 框架总体上更可靠和更健壮。同时还添加了两个新特性,包括概要分析支持,在 RPC 中使用 TorchScript 函数以及一些易于使用的增强功能。 此外,从 1.5 开始,PyTorch 不再支持 Python 2,今后,对 Python 的支持将仅限于 Python 3,特别是 Python 3.5、3.6、3.7 和 3.8。 更多具体的细节见发布公告: https://pytorch.org/blog/pytorch-1-dot-5-released-with-new-and-updated-apis

优秀的个人博客,低调大师

三行Python代码,让数据预处理速度提高2到6倍

在 Python 中,我们可以找到原生的并行化运算指令。本文可以教你仅使用 3 行代码,大大加快数据预处理的速度。 Python 是机器学习领域内的首选编程语言,它易于使用,也有很多出色的库来帮助你更快处理数据。但当我们面临大量数据时,一些问题就会显现…… 目前,大数据(Big Data)这个术语通常用于表示包含数十万数据点的数据集。在这样的尺度上,工作进程中加入任何额外的计算都需要时刻注意保持效率。在设计机器学习系统时,数据预处理非常重要——在这里,我们必须对所有数据点使用某种操作。 在默认情况下,Python 程序是单个进程,使用单 CPU 核心执行。而大多数当代机器学习硬件都至少搭载了双核处理器。这意味着如果没有进行优化,在数据预处理的时候会出现「一核有难九核围观」的情况——超过 50% 的算力都会被浪费。在当前四核处理器(英特尔酷睿 i5)和 6 核处理器(英特尔酷睿 i7)大行其道的时候,这种情况会变得更加明显。 幸运的是,Python 库中内建了一些隐藏的特性,可以让我们充分利用所有 CPU 核心的能力。通过使用 Python 的 concurrent.futures 模块,我们只需要 3 行代码就可以让一个普通的程序转换成适用于多核处理器并行处理的程序。 标准方法 让我们举一个简单的例子,在单个文件夹中有一个图片数据集,其中有数万张图片。在这里,我们决定使用 1000 张。我们希望在所有图片被传递到深度神经网络之前将其调整为 600×600 像素分辨率的形式。以下是你经常会在 GitHub 上看到的标准 Python 代码: import glob import os import cv2 ### Loop through all jpg files in the current folder ### Resize each one to size 600x600 for image_filename in glob.glob("*.jpg"): ### Read in the image data img = cv2.imread(image_filename) ### Resize the image img = cv2.resize(img, (600, 600)) 上面的程序遵循你在处理数据脚本时经常看到的简单模式: 1. 首先从需要处理内容的文件(或其他数据)列表开始。 2. 使用 for 循环逐个处理每个数据,然后在每个循环迭代上运行预处理。 让我们在一个包含 1000 个 jpeg 文件的文件夹上测试这个程序,看看运行它需要多久: time python standard_res_conversion.py 在我的酷睿 i7-8700k 6 核 CPU 上,运行时间为 7.9864 秒!在这样的高端 CPU 上,这种速度看起来是难以让人接受的,看看我们能做点什么。 更快的方法 为了便于理解并行化的提升,假设我们需要执行相同的任务,比如将 1000 个钉子钉入木头,假如钉入一个需要一秒,一个人就需要 1000 秒来完成任务。四个人组队就只需要 250 秒。 在我们这个包含 1000 个图像的例子中,可以让 Python 做类似的工作: ●将 jpeg 文件列表分成 4 个小组; ●运行 Python 解释器中的 4 个独立实例; ●让 Python 的每个实例处理 4 个数据小组中的一个; ●结合四个处理过程得到的结果得出最终结果列表。 这一方法的重点在于,Python 帮我们处理了所有棘手的工作。我们只需告诉它我们想要运行哪个函数,要用多少 Python 实例,剩下的就交给它了!只需改变三行代码。实例: import glob import os import cv2 import concurrent.futures def load_and_resize(image_filename): ### Read in the image data img = cv2.imread(image_filename) ### Resize the image img = cv2.resize(img, (600, 600)) ### Create a pool of processes. By default, one is created for each CPU in your machine. with concurrent.futures.ProcessPoolExecutor() as executor: ### Get a list of files to process image_files = glob.glob("*.jpg") ### Process the list of files, but split the work across the process pool to use all CPUs ### Loop through all jpg files in the current folder ### Resize each one to size 600x600 executor.map(load_and_resize, image_files) 从以上代码中摘出一行: with concurrent.futures.ProcessPoolExecutor() as executor: 你的 CPU 核越多,启动的 Python 进程越多,我的 CPU 有 6 个核。实际处理代码如下: executor.map(load_and_resize, image_files) 「executor.map()」将你想要运行的函数和列表作为输入,列表中的每个元素都是我们函数的单个输入。由于我们有 6 个核,我们将同时处理该列表中的 6 个项目! 如果再次用以下代码运行我们的程序: time python fast_res_conversion.py 我们可以将运行时间降到 1.14265 秒,速度提升了近 6 倍! 注意:在生成更多 Python 进程及在它们之间整理数据时会有一些开销,所以速度提升并不总是这么明显。但是总的来说,速度提升还是非常可观的。 它总是那么快吗? 如果你有一个数据列表要处理,而且在每个数据点上执行相似的运算,那么使用 Python 并行池是一个很好的选择。但有时这不是最佳解决方案。并行池处理的数据不会在任何可预测的顺序中进行处理。如果你对处理后的结果有特殊顺序要求,那么这个方法可能不适合你。 你处理的数据也必须是 Python 可以「炮制」的类型。所幸这些指定类别都很常见。以下来自 Python 官方文件: ●None, True, 及 False ●整数、浮点数、复数 ●字符串、字节、字节数组 ●只包含可挑选对象的元组、列表、集合和字典 ●在模块顶层定义的函数(使用 def ,而不是 lambda ) ●在模块顶层定义的内置函数 ●在模块顶层定义的类 ●这种类的实例,其 __dict__ 或调用__getstate__() 的结果是可选择的(参见「Pickling Class Instances」一节)。 原文发布时间为:2018-10-5 本文来自云栖社区合作伙伴“CDA数据分析师”,了解相关信息可以关注“CDA数据分析师”。

优秀的个人博客,低调大师

【Java入门提高篇】Day26 Java容器类详解(八)HashSet源码分析

前面花了好几篇的篇幅把HashMap里里外外说了个遍,大家可能对于源码分析篇已经讳莫如深了。别慌别慌,这一篇来说说集合框架里最偷懒的一个家伙——HashSet,为什么说它是最偷懒的呢,先留个悬念,看完本文之后,你就会知道所言不假了。 本篇将从以下几点来进行介绍: 1.HashSet的特点和使用场景 2.HashSet的示例 3.HashSet的继承结构图 4.HashSet的源码解析 HashSet的特点和使用场景 HashSet是Set家族的一员,所以也具有着Set的全部性质,比如元素无序,元素不可重复,但HashSet也有它自己的一些特性,比如它的查找效率很高,跟HashMap的查找效率一样高(滑稽,看完源码分析你就知道为什么了),它的基本操作如,add/remove/contains/size等都只需要常量时间的开销,并且允许存在null值。 所以HashSet的一个很重要的应用就是去重,把一堆存在重复的数据往HashSet里一丢,里面的元素因为是不会存在重复的,所以再取出来的时候就已经是去重过的数据了,这样HashSet就像一个筛子,把数据筛选了一次。另外HashSet由于其查找效率很高,所以也用于数据的查找,比如将处理过的数据往里面一丢,处理下一个数据的时候先到HashSet中查找一次,如果存在则说明已经处理过,不存在则继续处理。 HashSet的示例 接下来,看一个HashSet的小栗子吧。 1 public class Test { 2 3 public static void main(String[] args){ 4 //nameList中可以存在重复元素,且顺序跟插入的顺序相同 5 List<String> nameList = new ArrayList<>(); 6 nameList.add("Alice"); 7 nameList.add("Frank"); 8 nameList.add("Charles"); 9 nameList.add("Emma"); 10 nameList.add("Jessie"); 11 nameList.add("Frank"); 12 System.out.println(nameList); 13 14 //将列表里的元素插入到Set后,可以去除重复元素,但是没有顺序 15 System.out.println("====add===="); 16 Set<String> nameSet = new HashSet<>(); 17 for (String name : nameList){ 18 nameSet.add(name); 19 } 20 System.out.println(nameSet); 21 22 System.out.println("====contains===="); 23 System.out.println(nameSet.contains("Frank")); 24 System.out.println(nameSet.contains("Bob")); 25 26 System.out.println(nameSet.containsAll(nameList)); 27 28 System.out.println("====remove===="); 29 nameSet.remove("Frank"); 30 System.out.println(nameSet); 31 32 nameSet.forEach(System.out::println); 33 34 System.out.println("====Iterator===="); 35 Iterator iterator = nameSet.iterator(); 36 while (iterator.hasNext()){ 37 System.out.println(iterator.next()); 38 } 39 40 } 41 } 输出如下: [Alice, Frank, Charles, Emma, Jessie, Frank] ====add==== [Charles, Alice, Jessie, Frank, Emma] ====contains==== true false true ====remove==== [Charles, Alice, Jessie, Emma] Charles Alice Jessie Emma ====Iterator==== Charles Alice Jessie Emma HashSet的继承结构图 HashSet是继承自AbstractSet类的,同时实现了Set接口,Serializable接口,Cloneable接口,AbstractSet是Set的便利类,实现了Set接口的部分方法框架,AbstractSet里的方法其实很少,它继承自AbstractCollection类,同时实现了Set接口。 1 public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> { 2 3 protected AbstractSet() { 4 } 5 6 // 比较和哈希 7 8 /** 9 * 比较两个HashSet是否相等 10 * 先比较是否是同一个引用,然后判断o是否实现了Set接口 11 * 再比较它们的大小是否一致,最后判断是否包含了o中所有元素 12 */ 13 public boolean equals(Object o) { 14 if (o == this) 15 return true; 16 17 if (!(o instanceof Set)) 18 return false; 19 Collection<?> c = (Collection<?>) o; 20 if (c.size() != size()) 21 return false; 22 try { 23 return containsAll(c); 24 } catch (ClassCastException unused) { 25 return false; 26 } catch (NullPointerException unused) { 27 return false; 28 } 29 } 30 31 /** 32 * hashCode方法,计算所有元素的hashCode之和 33 */ 34 public int hashCode() { 35 int h = 0; 36 Iterator<E> i = iterator(); 37 while (i.hasNext()) { 38 E obj = i.next(); 39 if (obj != null) 40 h += obj.hashCode(); 41 } 42 return h; 43 } 44 45 /** 46 * 移除所有在集合c中的元素 47 * 如果c中元素个数小于该Set中的元素个数,则遍历c中的元素,使用Set中的remove方法进行移除。 48 * 相反,如果c中的元素个数大于Set中的元素个数,则遍历该Set中的元素,如果存在于c中,则调用迭代器的remove方法进行移除。 49 */ 50 public boolean removeAll(Collection<?> c) { 51 Objects.requireNonNull(c); 52 boolean modified = false; 53 54 if (size() > c.size()) { 55 for (Iterator<?> i = c.iterator(); i.hasNext(); ) 56 //这里其实用了一个很巧妙的位操作,只要remove有一次成功,则返回true,modified就会变成true,之后不管remove返回true还是false,与modified进行或操作的时候结果都是true,所以只要remove中有一次是成功的,modified变量就是true 57 modified |= remove(i.next()); 58 } else { 59 for (Iterator<?> i = iterator(); i.hasNext(); ) { 60 if (c.contains(i.next())) { 61 i.remove(); 62 modified = true; 63 } 64 } 65 } 66 return modified; 67 } 68 69 } HashSet的源码解析 先来看看源码的结构: 相比HashMap是不是方法少了很多很多,也许你会好奇,HashSet是如何用将精华操作塞在这么少的方法中的,嗯,一起来看看它是怎样实现的吧: public Iterator<E> iterator() { return map.keySet().iterator(); } public int size() { return map.size(); } public boolean isEmpty() { return map.isEmpty(); } public boolean contains(Object o) { return map.containsKey(o); } public boolean add(E e) { return map.put(e, PRESENT)==null; } public boolean remove(Object o) { return map.remove(o)==PRESENT; } public void clear() { map.clear(); } @SuppressWarnings("unchecked") public Object clone() { try { HashSet<E> newSet = (HashSet<E>) super.clone(); newSet.map = (HashMap<E, Object>) map.clone(); return newSet; } catch (CloneNotSupportedException e) { throw new InternalError(e); } } 看完你也许会觉得,WTF???主要方法全部是一行代码解决??来看看这个map到底是何方神圣: private transient HashMap<E,Object> map; 惊不惊喜,意不意外,HashSet其实就是里面放了一个HashMap实例,所有操作都是通过HashMap去完成的,至于它的元素不可重复特性,也是借助于HashMap的键值不可重复实现的。嗯,说它是最懒的容器类不过分吧。 再来看看它的几个构造函数: 1 /** 2 * 构造一个空的HashSet,其中的HashMap实例使用默认的初始容量(16)和默认的装载因子(0.75) 3 */ 4 public HashSet() { 5 map = new HashMap<>(); 6 } 7 8 /** 9 * 构建一个包含指定集合所有元素的HashSet,其中的HashMap实例使用默认的装载因子(0.75)和能够容纳下集合中所有元素的初始容量(别忘了,必须是2的幂次方) 10 */ 11 public HashSet(Collection<? extends E> c) { 12 map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); 13 addAll(c); 14 } 15 16 /** 17 * 构建一个空的HashSet,其中的HashMap实例使用指定的加载因子和初始容量 18 */ 19 public HashSet(int initialCapacity, float loadFactor) { 20 map = new HashMap<>(initialCapacity, loadFactor); 21 } 22 23 /** 24 * 构建一个空的HashSet,其中的HashMap使用默认的加载因子和指定的容量大小 25 */ 26 public HashSet(int initialCapacity) { 27 map = new HashMap<>(initialCapacity); 28 } 29 30 /** 31 * 构建一个空的LinkedHashSet,这是一个包私有的构造器,仅仅被LinkedHashSet使用,里面的HashMap是一个LinkedHashMap实例,使用指定的容量和装载因子 32 * dummy是一个没有意义的参数,目的是为了跟上面的构造函数区分开来,如果没有这个参数,将不能进行有效重载 33 */ 34 HashSet(int initialCapacity, float loadFactor, boolean dummy) { 35 map = new LinkedHashMap<>(initialCapacity, loadFactor); 36 } 37 38 所以,其实可以灵活定制HashSet的大小和装载因子,只是一般情况下,使用默认的即可,除非知道里面要放的元素个数,并且数量比较大时,才需要进行指定容量,这样可以减少扩容次数。 再来看看剩下的几个函数: /** * 序列化 */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { // Write out any hidden serialization magic s.defaultWriteObject(); // Write out HashMap capacity and load factor s.writeInt(map.capacity()); s.writeFloat(map.loadFactor()); // Write out size s.writeInt(map.size()); // Write out all elements in the proper order. for (E e : map.keySet()) s.writeObject(e); } /** * 反序列化 */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in any hidden serialization magic s.defaultReadObject(); // Read capacity and verify non-negative. int capacity = s.readInt(); if (capacity < 0) { throw new InvalidObjectException("Illegal capacity: " + capacity); } // Read load factor and verify positive and non NaN. float loadFactor = s.readFloat(); if (loadFactor <= 0 || Float.isNaN(loadFactor)) { throw new InvalidObjectException("Illegal load factor: " + loadFactor); } // Read size and verify non-negative. int size = s.readInt(); if (size < 0) { throw new InvalidObjectException("Illegal size: " + size); } // Set the capacity according to the size and load factor ensuring that // the HashMap is at least 25% full but clamping to maximum capacity. capacity = (int) Math.min(size * Math.min(1 / loadFactor, 4.0f), HashMap.MAXIMUM_CAPACITY); // Constructing the backing map will lazily create an array when the first element is // added, so check it before construction. Call HashMap.tableSizeFor to compute the // actual allocation size. Check Map.Entry[].class since it's the nearest public type to // what is actually created. SharedSecrets.getJavaOISAccess() .checkArray(s, Map.Entry[].class, HashMap.tableSizeFor(capacity)); // Create backing HashMap map = (((HashSet<?>)this) instanceof LinkedHashSet ? new LinkedHashMap<E,Object>(capacity, loadFactor) : new HashMap<E,Object>(capacity, loadFactor)); // Read in all elements in the proper order. for (int i=0; i<size; i++) { @SuppressWarnings("unchecked") E e = (E) s.readObject(); map.put(e, PRESENT); } } /** * 可分割式迭代器 */ public Spliterator<E> spliterator() { return new HashMap.KeySpliterator<E,Object>(map, 0, -1, 0, 0); } 嗯,HashSet的介绍就这么多了,很简单吧。 之后还会继续将容器家族中常见的容器类进行源码解析,如LinkedList,LinkedHashMap,LinkedHashSet,TreeMap,TreeSet。嗯,所以预计关于容器类还有至少五篇文章,希望大家能耐心看下去,当然,如果对于源码解析实在没什么兴趣,也可以先跳过这一部分,先知道怎么用就好了。 之后还会努力更新,欢迎大家继续关注。真正重要的东西,用眼睛是看不见的。

优秀的个人博客,低调大师

如何才能真正的提高自己,成为一名出色的架构师?

一、广度: 广度指的是架构师应该对所在领域的主流技术体系有一个全面清晰的认识,每一种技术不需要很深入的了解,但必须知道每种技术的“3W”: 1,Why:每种技术的由来,为什么会出现这种技术,这个技术是用来解决什么问题的? 2,What:每种技术是什么?技术的基本组成部分是什么? 3,Which:解决同一问题的相同技术各自的优缺点是什么,更适合哪种场景?比如,ORM框架(Hibernate与IBatis),MVC框架(Struts与SpringMVC),大数据技术(Hadoop与Spark)它们各自的优缺点是什么,只有清晰认识同一类型技术的优缺点,才能在技术选型时能够使用更加合理的技术。 广度的学习方法:对各主流技术一一通过搜索引擎了解其3W的内容。二、高度: 高度指的是架构师应具备对客观事物的“拔高”能力,能够从纷繁杂乱的信息中建立秩序,也就是我们一般所说的抽象能力。 抽象能力包括: 1,业务抽象:能够软件和产品的复杂的需求中抽象核心业务实体,并给各业务实体建立合理的关系; 2,技术抽象:能够对复杂的技术架构进行分层抽象、服务抽象(微服务抽象)、组件抽象,并为各层和各服务之间的调用建立合理的“关系”; 高度的学习方法:深入理解和学习面向对象、设计模式,琢磨优秀开源框架的设计原理和设计思想。三、深度: 深度指的是架构师能对主流技术有较为深入的理解,主要包括: 1,可以不了解源代码,但对主流技术的原理,运作机理有一个基本的理解; 2,至少对一种技术有深入的认识,是这种技术的专家,熟悉其源代码以上2点,1为必须,2为非必须深度的学习方法:上文已说。四、宽度: 宽度指的是架构师能够熟知当前的技术前沿和热点,能够使用新的技术解决问题。比如,微服务、大数据、云计算、人工智能等。 宽度的学习方法:可以使用手机订阅相关的技术资讯了解,定期了解即可,对于跟所负责工作相关的技术进行进一步的了解。 小结:广度决定了系统架构技术选型的合理性;高度决定了系统架构设计的合理性;深度决定了系统架构的优化能力;宽度决定了系统架构的领先性,不至于三五年被淘汰四度缺一不可! 欢迎工作一到五年的Java工程师朋友们加入Java架构开发:468947140 点击链接加入群聊【Java-BATJ企业级资深架构】:https://jq.qq.com/?_wv=1027&k=5zMN6JB 本群提供免费的学习指导 架构资料 以及免费的解答 不懂得问题都可以在本群提出来 之后还会有职业生涯规划以及面试指导

优秀的个人博客,低调大师

mysql 自动检查并启动slave 线程的小方法,提高运维效率

问题 某些公司数据库架构是两主多从,双活跨IDC机房,这样就存在一个问题。跨机房的数据库同步,必然会 存在网络抖动,异常引起的slave io,slave sql线程关闭的情况。 2.解决的思虑 1)写一个脚本定时监控slave 状态 2)使用shell 写就可以 3)使用crontab 每分钟检查,判断,然后根据判断执行start slave 就可以了。 具体的写法,需要大家自己动手来写了,只有这样才能有提升。 知识点 1)crontab 用法,每多少分钟检查一次 2) shell if [] then 判断即可完成。 本文转自 roidba 51CTO博客,原文链接:http://blog.51cto.com/roidba/1887163,如需转载请自行联系原作者

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册