map

阅读 / 问答 / 标签

在maple 15作图中,plot(xe^(-x), x = -4 .. 4)出错

加上 y 轴的绘图区域试试看plot(x*exp(-x), x = -4 .. 4, y = -4 ..4)plot(x*exp(-x), x = -2 .. 4, y = -4 .. 2)

英语custom username mapping怎么翻译?

custom username mapping 自定义用户名映射

unturned中maple plank如何获得?

在 Unturned 游戏中,可以使用以下方法获取 Maple Plank:在游戏中找到 Maple Tree,并使用木斧将其砍下。使用木斧在 Maple Tree 上制作 Maple Log。使用木斧将 Maple Log 加工成 Maple Plank。在 Maple Plank 上使用木斧进行修整,将其变成高质量的 Maple Plank。在游戏中查找 Maple Plank,或者与其他玩家进行交易获取 Maple Plank

求防弹少年团《MAP OF THE SOUL:PERSONA》的mp3资源。谢谢

高品质mp3链接给你,有疑问找我。你要的链接:https://pan.baidu.com/s/1WTQVuEAnNt7lBDbu4i_yMg 提取码:u4jh

surfer种的overlap map在哪个位置

如图: 各版本差不多,下面是Surfer13,命令在MAP菜单下。只有选择两个对象以后,此命令才可以使用,多用于在等值线图上增加散点图等。

MATAsuperstar和MAPEX军火库哪个好

后者,性价比更高,质量用途,也更广

请问WTL中BEGIN_MSG_MAP_EX和BEGIN_MSG_MAP具体有什么异同?

调转到代码看这二个宏的定义不就知道了

python grpc如何给proto文件中map类型的变量赋值?

改完之后,你可以选择project->clean,clean后你项目的R.java文件就会重新生成,所有的资源ID会重新分配,这样子你所修改的资源才能被Android真正识别,有时这个操作不是必要的,但是如果出现你修改了资源后,你的项目中出现了一些问题,那么执行Clean是一个必须的选择,这些资源包括drawable下的图片,布局里id的修改,values下资源的修改,你可以着手试一下 Good luck

为什么google protobuf不支持map的序列化和反序列化

现在它是支持的。proto2的文档就已经提到了Maps(Language Guide),但我用protoc2.6编译的时候,map关键字无法通过编译,protoc3.0编译正常,proto举例:message Person { required int32 id = 1; required string name = 2; optional string email = 3; map<string, string> values= 4; } 另外,官方文档(https://developers.google.com/protocol-buffers/docs/proto#Maps)说了:The map syntax is equivalent to the following on the wire, so protocol buffers implementations that do not support maps can still handle your data:message MapFieldEntry { key_type key = 1; value_type value = 2;}repeated MapFieldEntry map_field = N;

为什么google protobuf不支持map的序列化和反序列化

现在它是支持的。proto2的文档就已经提到了Maps(Language Guide),但我用protoc2.6编译的时候,map关键字无法通过编译,protoc3.0编译正常,proto举例:message Person {required int32 id = 1;required string name = 2;optional string email = 3;map<string, string> values= 4;} 另外,官方文档(https://developers.google.com/protocol-buffers/docs/proto#Maps)说了:The map syntax is equivalent to the following on the wire, so protocol buffers implementations that do not support maps can still handle your data:message MapFieldEntry {key_type key = 1;value_type value = 2;}repeated MapFieldEntry map_field = N;

如何去获得plink的ped和map文件

可以使用vcftools 使用--plink命令就可以了

罗马市内交通攻略romapass怎么用划算

印象中第一次知道罗马是因为“条条大路通罗马”这句话,其实可以去了解一下罗马这个地方,你在了解了以后就会喜欢上这个地方的,下面我很还是先了解一下关于这里的交通吧。romapass此行我们使用的是3日的romapass,购于中央火车站,2张pass银联借记卡共扣费598元,实际折下来差不多38欧一张。两个景点门票使用在了罗马斗兽场和博格塞博物馆上,斗兽场门票12欧+博格塞门票22欧,加之我们每天公交车差不多在3次左右(单买车票1.5欧/张,100分钟内地铁一次,公交不限次数),算下来pass还是很划算的。但我觉得pass的价值更多体现在方便上,对于第一次到欧洲的我们来说,不用操着破破的英语去找地方买车票,实在是省了不少心。如果你在罗马停留时间达到或超过三天,有2个以上景点的计划,并且不是暴走一族,那么建议购买3日pass,相对而言2日pass因为只包含一个景点门票,含金量较3日的不足,如果怕买票麻烦,可以买,但就不是那么划算了。需要注意的是,火车站、机场romapass的官方专柜是不找零的,也就是说要么你给刚刚好的现金,要么就需要刷卡。公交罗马公交线路密集,基本可以到达你想去的任何角落,但罗马的公交车只有在有乘客上下的站台才会停靠,如果没有人上下,会直接开往下一个站而没有任何提示。如果你要下车,需要在车到站前,按车内栏杆上的红色按钮,此时会有叮铃叮铃的铃声,车内的液晶屏会显示“有乘客想要下站”(当然是意大利文和英文版),然后司机就会在下一站停靠。这对不熟悉罗马的游客来说,很容易坐过站,我们就在去西班牙广场时坐过了一站,因此建议在乘坐罗马公交时,同步打开地图软件,这样基本可以免除坐错、坐过的问题;火车罗马有两个火车站!两个火车站!两个火车站!——之所以强调是因为我们在离开罗马去佛罗伦萨的时候,差一点点就因为走错火车站而错过火车。中央火车站(Termini),是罗马最主要的车站,也是机场专列LeonardoExpress的终点,从这里能出发到各个城市,而另一车站RomaTiburtina在城市的北边,相对比较边缘化一点。此前作准备的时候,虽然知道有这么一个车站,但似乎很少有游客会去到那里,介绍少之又少,于是我订票的时候完全没有去注意发车车站的信息。于是就有这么凑巧,我定那班车就是从Tiburtina发车的。。。我们在清晨六点过的Termini大厅看到车号和目的地都吻合但发车时间晚了十五分钟,多方询问才在明白自己走!错!站!了!!而此时距离发车时间只有20分钟而已。。。你说惊不惊喜,意不意外?所幸接受我问询的工作人员比较友善,告诉我虽然车站不同但这班车是从Tiburtina发车,经TERMINI去往佛罗伦萨的,因此也可以从termini上车。我们的这一教训充分说明,出门在外,尤其是陌生的地方,车票信息核查再仔细都不为过,千万不要想当然,如果你跟我们一样走错车站也请不要慌张,似乎很多班车都是两个站都会经过的(大概就跟早些年菜园坝火车站和龙头寺火车站类似),意大利铁路上车的检票并不严格,换个车站上车似乎也是可以的。治安去之前不少朋友提醒我注意安全,到了罗马来来往往全是高高大大的白人、黑人,一开始我们确有些惴惴不安,不过几天下来,除了在西班牙广场遇到疑似骗纸之外,没有任何意外发生,所遇到的路人基本都很友善,要知道我们每天晚上基本在外面活动到十点多种,有一天甚至在斗兽场待到近十二点,也许是旅游淡季骗纸小偷们都休假去了?总之我觉得出门在外当然要多加小心,但过分妖魔化还是没有必要的

猎头行业单词求翻译:maping 和 soursing, 分别是什么意思?求大侠指教!

maping 就是你在找客户要求的目标公司时找到某个部门的人的联系记录汇总。打个比方:例如你要找的是A公司销售部门的,你通过CC或者其他渠道了解到这个部门有ABCD4个人,A是销售经理,负责快消渠道,B是销售主管,负责的是零售渠道。 C和D都是销售专员,负责的是代理渠道。你把这些人的职位,名字,联系方式,负责渠道,联系记录用一个表格的形式罗列出来就是maping。soursing是采购行业的常用的一个词,基本释义就是采购的意思,不过在英语单词中采购有purchase和sorursing,1. sourcing指开发供应商,偏重于对整体项目的分析,对潜在的预测有比较高的要求,同时还可能负责前期的供应商的寻找和筛选,sourcing强调的是对外部资源的调查,分类和评比;2. purchase指的是项目的执行者;

压力0.006map等于多少kap

0.006Mpa =0.006*1000Kpa = 6Kpa

Velocity中如何定义一个空的Map变量,然后循环地向其中添加元素?

首先你要明确,velocity主要是引用java中定义的变量,很少有自己定义的变量,或者自己只能简单的定义一些变量,例如map对象他只能定义一个变量,然后将java中定义的map对象绑定到velocity定义的变量上.velocity是不能定义完变量,然后向里面add元素的,因为没有add类方法.

将std::mutex放入std::map中

参考: c++ - Map of mutex c++11 - Stack Overflow std::mutex不好放进map的主要原因是: TL;DR: just use operator [] like std::map<std::string, std::mutex> map; map[filename]; Why do you need to use an std::unique_ptr in the first place? I had the same problem when I had to create an std::map of std::mutex objects. The issue is that std::mutex is neither copyable nor movable, so I needed to construct it "in place". I couldn"t just use emplace because it doesn"t work directly for default-constructed values. There is an option to use std::piecewise_construct like that: but it"s IMO complicated and less readable. My solution is much simpler - just use the operator[] - it will create the value using its default constructor and return a reference to it. Or it will just find and return a reference to the already existing item without creating a new one.

信号量vs互斥锁(Semaphore vs Mutex)

信号量是一个被线程共享的非负变量。信号量是一个发信号的机制。一个等待一个信号量的线程可以被其他线程通知(signal)。这个机制通过 wait 和 signal 两个原子操作(atomic operations)来实现进程同步。 一个信号量要么允许访问资源,要么不允许访问资源。二者只能选其一。而具体是哪一种,则要看设置。 详情可参考《 信号量:二进位信号量和计数信号量 》这篇文章。 互斥锁其实是一个对象。Mutex的全称是Mutual Exclusion Object,也就是互斥锁是一个互斥对象。它是一种特殊的二进位信号量(binary semaphore),用来控制访问共享区域资源。它包括一个优先级继承机制,以避免扩展的优先级反转问题。它允许当前优先级较高的任务在阻塞状态下维持的时间尽可能的少。然而,优先级继承并不能完全避免优先级反转,而只会最小化其影响。 对于单个缓冲区(single buffer),我们可以将4kb缓冲区分成四个1kb缓冲区。信号量可以与这四个缓冲区相关联。这允许用户和生产者同时处理不同的缓冲区。 互斥锁用于提供互斥,它使得拥有钥匙(key or mutex)的生产者才能访问资源。只要生产者占用了缓冲区(buffer),用户必须等待,反之亦然。在互斥锁的机制中,整块缓冲区始终只能提供给一个线程访问。 下面列举信号量的优点: 下面列举互斥锁的优点: 下面列举信号量的缺点: 下面列举互斥锁的缺点:

MapReduce和hadoop什么关系和区别??

hadoop是google的云计算系统的开源实现,谷歌集群系统主要包括三个部分:分布式文件系统GFS,分布式并行计算模型map/reduce,以及分布式数据库Bigtable,hadoop也实现了这三个,GFS对应HDFS,hadoop的map/reduce对应谷歌的map/reduce模型,Hbase对应Bigtable。也就是map/reduce是谷歌提出的一种云计算模型,hadoop用java开源实现了

MapReduce 知识

客户端(client) 提交MapReduce作业 JobTracker 1.作业调度:将一个作业(Job)分成若干个子任务分发到taskTraker中去执行 2.任务监控:TaskTracker发送心跳给JobTracker报告自己的运行状态,以让JobTracker能够监控到他 3.资源管理:每个任务向JobTracker申请资源 4.监控过程中发现失败或者运行过慢的任务,对他进行重新启动 TaskTracker 主动发送心跳给jobTracker并与JobTracker通信,从而接受到JobTracker发送过来需要执行的任务 资源表示模型 用于描述资源表示形式,Hadoop1.0使用“槽位(slot)”组织各个节点的资源,为了简化资源的管理,Hadoop将各个节点上资源(CPU、内存、网络IO、磁盘IO等等)等量切分成若干份,每一份用“slot”表示,同时规定一个task可根据实际情况需要占用多个”slot”。 简单的说:hadoop1.0将多维度的资源进行了抽象,使用“slot”来表示,从而简化对资源的管理。 资源分配模型 而资源分配模型则决定如何将资源分配给各个作业/任务,在Hadoop中,这一部分由一个插拔式的调度器完成。 更进一步说,slot相当于运行的“许可证”,一个任务只有获得“许可证”后,才能够获得运行的机会,这也意味着,每一个节点上的slot的数量决定了当前节点能够并发执行多少个任务。Hadoop1.0为了区分MapTask跟ReduceTask所使用资源的差异,进一步将slot分为MapSlot跟ReduceSlot,他们分别只能被MapTask跟ReduceTask使用。 Hadoop集群管理员可根据各个节点硬件配置和应用特点为它们分配不同的map slot数(由参数mapred.tasktracker.map.tasks.maximum指定)和reduce slot数(由参数mapred.tasktrackerreduce.tasks.maximum指定) 静态资源配置 。 采用了静态资源设置策略,即每个节点事先配置好可用的slot总数,这些slot数目一旦启动后无法再动态修改。 资源无法共享 。 Hadoop 1.0将slot分为Map slot和Reduce slot两种,且不允许共享。对于一个作业,刚开始运行时,Map slot资源紧缺而Reduce slot空闲,当Map Task全部运行完成后,Reduce slot紧缺而Map slot空闲。很明显,这种区分slot类别的资源管理方案在一定程度上降低了slot的利用率。 资源划分粒度过大 。资源划分粒度过大,往往会造成节点资源利用率过高或者过低 ,比如,管理员事先规划好一个slot代表2GB内存和1个CPU,如果一个应用程序的任务只需要1GB内存,则会产生“资源碎片”,从而降低集群资源的利用率,同样,如果一个应用程序的任务需要3GB内存,则会隐式地抢占其他任务的资源,从而产生资源抢占现象,可能导致集群利用率过高。 没引入有效的资源隔离机制 。Hadoop 1.0仅采用了基于jvm的资源隔离机制,这种方式仍过于粗糙,很多资源,比如CPU,无法进行隔离,这会造成同一个节点上的任务之间干扰严重。 主要是InputFormat。InputFormat类有2个重要的作用: 1)将输入的数据切分为多个逻辑上的InputSplit,其中每一个InputSplit作为一个map的输入。 2)提供一个RecordReader,用于将InputSplit的内容转换为可以作为map输入的k,v键值对。 系统默认的RecordReader是 LineRecordReader ,它是 TextInputFormat (FileInputFormat的子类)对应的RecordReader; Map读入的Key值是偏移量,Value是行内容。 两个Mapper各自输入一块数据,由键值对构成,对它进行加工(加上了个字符n),然后按加工后的数据的键进行分组,相同的键到相同的机器。这样的话,第一台机器分到了键nk1和nk3,第二台机器分到了键nk2。 接下来再在这些Reducers上执行聚合操作(这里执行的是是count),输出就是nk1出现了2次,nk3出现了1次,nk2出现了3次。从全局上来看,MapReduce就是一个分布式的GroupBy的过程。 从上图可以看到,Global Shuffle左边,两台机器执行的是Map。Global Shuffle右边,两台机器执行的是Reduce。 Hadoop会将输入数据划分成等长的数据块,成为数据分片。Hadoop会为每个分片构建一个map任务。并行的处理分片时间肯定会少于处理整个大数据块的时间,但由于各个节点性能及作业运行情况的不同,每个分片的处理时间可能不一样,因此, 把数据分片切分的更细可以得到更好的负载均衡 。 但另一方面,分片太小的话,管理分片和构建map任务的时间将会增多。因此,需要在hadoop分片大小和处理分片时间之间做一个权衡。对大多数作业来说,一个分片大小为64MB比较合适,其实,Hadoop的默认块大小也是64MB。 我们上面看到了hadoop的数据块大小与最佳分片大小相同,这样的话,数据分片就不容易跨数据块存储,因此,一个map任务的输入分片便可以直接读取本地数据块,这就 避免了再从其它节点读取分片数据 ,从而节省了网络开销。 map的任务输出是 写入到本地磁盘而非HDFS的 。那么为什么呢?因为map任务输出的是中间结果,一旦map任务完成即会被删除,如果把它存入HDFS中并实现备份容错,未免有点大题小做。如果一个map任务失败,hadoop会再另一个节点重启map一个map任务。 而reduce任务并不具备数据本地化优势——单个reduce任务的输入通常来自所有mapper输出。一般排序过的map输出需要通过 网络传输 发送到运行reduce任务的节点,并在reduce端进行合并。reduce的输出通常需要存储到HDFS中以实现可靠存储。每个reduce输出HDFS块第一个复本会存储在本地节点,而其它复本则存储到其它节点,因此reduce输出也需要占用网络带宽。 1.调整reduce个数方法(1) (1)每个Reduce处理的数据量默认是256MB (2)每个任务最大的reduce数,默认为1009 (3)计算reducer数的公式 2.调整reduce个数方法(2) 在hadoop的mapred-default.xml文件中修改,设置每个job的Reduce个数 3.reduce个数并不是越多越好 (1)过多的启动和初始化reduce也会消耗时间和资源; (2)另外,有多少个reduce,就会有多少个输出文件,如果产生了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题; 在设置reduce个数的时候也需要考虑这两个原则:处理大数据利用适合的reduce数;使单个reduce任务处理数据大小要合适; 在进行map计算之前,mapreduce会根据输入文件计算输入分片(input split),每个输入分片(input split)针对一个map任务,输入分片(input split)存储的并非数据本身,而是一个分片长度和一个记录数据的位置的数组,输入分片(input split)往往和hdfs的block(块)关系很密切,我们没有设置分片的范围的时候,分片大小是由block块大小决定的,和它的大小一样。 比如把一个258MB的文件上传到HDFS上,假设block块大小是128MB,那么它就会被分成三个block块,与之对应产生三个split,所以最终会产生三个map task。我又发现了另一个问题,第三个block块里存的文件大小只有2MB,而它的block块大小是128MB,那它实际占用Linux file system的多大空间?答案是实际的文件大小,而非一个块的大小。最后一个问题是: 如果hdfs占用Linux file system的磁盘空间按实际文件大小算,那么这个”块大小“有必要存在吗?其实块大小还是必要的,一个显而易见的作用就是当文件通过append操作不断增长的过程中,可以通过来block size决定何时split文件。 1.每个输入分片会让一个map任务来处理,map输出的结果会暂且放在一个环形内存缓冲区中(该缓冲区的大小默认为100M,由io.sort.mb属性控制),当该缓冲区快要溢出时(默认为缓冲区大小的80%,由io.sort.spill.percent属性控制),会在本地文件系统中创建一个溢出文件,将该缓冲区中的数据写入这个文件。 2.在写入磁盘之前,线程首先根据reduce任务的数目将数据划分为相同数目的分区,也就是一个reduce任务对应一个分区的数据。这样做是为了避免有些reduce任务分配到大量数据,而有些reduce任务却分到很少数据,甚至没有分到数据的尴尬局面。其实分区就是对数据进行hash的过程。然后对每个分区中的数据进行 排序 ,如果此时设置了Combiner,将排序后的结果进行Combiner操作,主要是在map计算出中间文件前做一个简单的合并重复key值的操作,这样做的目的是让尽可能少的数据写入到磁盘。 3.当map任务输出最后一个记录时,可能会有很多的溢出文件,这时需要将这些文件合并。合并的过程中会不断地进行排序和Combiner操作,目的有两个:1.尽量减少每次写入磁盘的数据量;2.尽量减少下一复制阶段网络传输的数据量。最后合并成了一个 已分区且已排序 的文件。为了减少网络传输的数据量,这里可以将数据压缩,只要将mapred.compress.map.out设置为true就可以了。 4.将分区中的数据 拷贝 (网络传输)给相对应的reduce任务。有人可能会问:分区中的数据怎么知道它对应的reduce是哪个呢?其实map任务一直和其父TaskTracker保持联系,而TaskTracker又一直和JobTracker保持心跳。所以JobTracker中保存了整个集群中的宏观信息。只要reduce任务向JobTracker获取对应的map输出位置就ok了哦。 Reduce端: 1.Reduce会接收到不同map任务传来的数据,并且每个map传来的数据都是有序的。如果reduce端接受的数据量相当小,则直接存储在内存中(缓冲区大小由mapred.job.shuffle.input.buffer.percent属性控制,表示用作此用途的堆空间的百分比),如果数据量超过了该缓冲区大小的一定比例(由mapred.job.shuffle.merge.percent决定),则对 数据合并 后 溢写 到磁盘中。 2.随着溢写文件的增多,后台线程会将它们合并成一个更大的有序的文件,这样做是为了给后面的合并节省时间。其实不管在map端还是reduce端,MapReduce都是反复地执行排序,合并操作,现在终于明白了有些人为什么会说:排序是hadoop的灵魂。 3.合并的过程中会产生许多的中间文件(写入磁盘了),但MapReduce会让写入磁盘的数据尽可能地少,并且 最后一次合并的结果 并没有写入磁盘,而是直接输入到reduce函数。 Read阶段 :MapTask通过用户编写的RecordReader,从输入InputSplit中解析出一个个key/value Map阶段 :该节点主要是将解析出的key/value交给用户编写map()函数处理,并产生一系列新的key/value。 Collect收集阶段 :在用户编写map()函数中,当数据处理完成后,一般会调用OutputCollection.collect()输出结果。在该函数内部,它会将生成的 key/value分区 (调用Partitioner),并写入一个环形内存缓冲区中。 Spill阶段 :即“溢写”,当环形缓冲区满后,MapReduce会将数据写入本地磁盘上,生成一个临时文件。需要注意的是,将数据写入本地磁盘之前,先要对数据进行一次本地 排序 ,并在必要时对数据进行 combiner 、 压缩 等操作。 溢写阶段详情: 合并阶段 :当所有数据处理完成后,MapTask对所有临时文件进行一次合并,以确保最终只会生成一个数据文件。在进行文件合并过程中,MapTask以分区为单位进行合并。对于某个分区,它将采用多轮递归合并的方式。每轮合并io.sort.factor(默认100)个文件,并将产生的文件重新加入待合并列表中,对文件排序后,重复以上过程,直到最终得到一个大文件。让一个MapTask最终只生成一个数据文件,可避免同时打开大量文件和同时读取大量小文件产生的随机读取带来的开销。

创建一个HashMap对象,并在其中添加一些学生的姓名和他们的分数,键为学生姓名(

#include "stdafx.h"#include <iostream>#include <hash_map>#include <string>using namespace std;int _tmain(int argc, _TCHAR* argv[]){ stdext::hash_map<std::string, float> hm; hm.insert(std::make_pair<std::string, float>("A", 70.0)); hm.insert(std::make_pair<std::string, float>("C", 75.0)); hm.insert(std::make_pair<std::string, float>("B", 80.0)); stdext::hash_map<std::string, float>::iterator it; for(it = hm.begin(); it!= hm.end(); ++it) { cout <<it->first<<" "<<it->second << std::endl; } return 0;}

C++简单算法题,差一点做出来,我用map来做,运行结果和答案正好相反,但我实在不知如何把答案反过来?

你拼字符串时把str放到后面,拼出来的字符串就是正的了.改正后的程序如下图1图2(改动地方见注释)因为题目要求可以输入100位的整数,所以要用string来接收输入的数据,并用字符法计算每一位上的数字和.图4图5是改进的可以输入100位整数的程序(改动地方见注释)

C++ 为什么std::map赋值失败

sm_mHandletoWindow是std::map类型吧?map.insert应该使用sm_mHandletoWindow.insert(make_pair(m_hWnd, this)),而不用您自己构造pair。std::map<HWND, Window&>报什么错呢?

C++中如何如果定义一个关联容器map< int,vector > 如何用make_pair()给该容器插入元素

不知道你到底要把什么放map中,很明显语法上应该是 data_m.insert(make_pair(i, data));这才对。或者map<int, ID_Card> data_m2, 然后 data_m2.insert(make_pair(i, data[i]));

关于 STM32 复用重映射和调试I/O配置寄存器(AFIO_MAPR) 的库函数看不太懂,希望大侠能每一句都注释…

这函数实际是完成AFIO->MAPR寄存器的配置,我就是嫌这代码写的太烦了,所以直接对寄存器进行操作。比如将串口2重映射时,就是:AFIO->MAPR|=GPIO_Remap_USART2;要取消重映射,就是:AFIO->MAPR&=~GPIO_Remap_USART2;GPIO_Remap_USART2在stm32f10x_GPIO.h中是有定义的,AFIO->MAPR寄存器各个位的定义在参考手册中有详细描述。

STM32 GPIO_PinRemapConfig函数的问题。。

这个IO口,用了下载用的IO口,这句话将下载用的IO口转化为普通IO口,即关闭其下载功能。

Hibernate用注释进行映射。老是提示User is not mapped. 请问应怎样解决?

已经有人回答 greatdoudou

J.U.C锁之 Semaphore

Semaphore 名为"信号量"。 Semaphore用来管理内部许可证,当多个线程要访问竞争资源时可以通过Semaphore来控制并发访问竞争资源的线程数。当线程需要访问竞争资源时需要首先获取一个许可证,执行完毕在返还,如果许可证用完则,线程进入同步队列并阻塞。等待许可证返回唤醒。 主要特性 公平性 :支持公平性和非公平性。所谓公平表示在获取锁时逻辑是否要考虑当前正在排队等待线程。按照大白话来说就时公平表示不能插入强占资源。 应用场景 获取许可 释放许可 其他方法 Semaphore 使用AQS实现锁机制,AQS是AbstractQueuedSynchronizer的缩写,翻译过来就是"同步器",,它实现了Java函数中锁同步(synchronized),锁等待(wait,notify)功能。 AbstractQueuedSynchronizer是一个抽象类,我们可以编写自己类继承AQS重写获取独占式或共享式同步状态模板方法,实现锁锁同步(synchronized),锁等待(wait,notify)功能 AQS核心是一个同步状态,两个队列。它们实现了Java函数中锁同步(synchronized),锁等待(wait,notify),并在其基础上实现了独占式同步,共享式同步2中方式锁的实现。 无论独占式还时共享式获取同步状态成功则直接返回,失败则进入CLH同步队列并阻塞当前线程。当获取同步状态线程释放同步状态,AQS会选择从CLH队列head头部节点的第一个节点释放阻塞,尝试重写竞争获取同步状态,如果成功则将当前节点出队。如果失败则继续阻塞。 获取同步状态的线程也可以使用condition对象释放同步状态进入等待队列。只有等待其他线程使用condition.signal或condition.signAll()唤醒被从阻塞状态中释放重新竞争获取同步状态成功后从原来指令位置继续运行。 AQS实现了锁,必然存在一个竞争资源。AQS存在从一个int类型的成员变量state,我们把它称为同步状态,同步状态通常用做判断线程能否获取锁的依据 AQS 实现了锁那么总需要一个队列将无法获取锁的线程保存起来,方便在锁释放时通知队列中线程去重新竞争锁。 实现原理 同步队列又被称为CLH同步队列,CLH队列是通过 链式方式实现FIFO双向队列 。当线程获取同步状态失败时,AQS则会将当前线程构造成一个节点(Node)并将其加入到CLH同步队列,同时会阻塞当前线程,当同步状态被释放时,会把首节点后第一个节点的线程从阻塞状态下唤醒,唤醒的线程会尝试竞争同步状态,如果能获取同步状态成功,则从同步队列中出队。 实现原理 这里取消节点表示当前节点的线程不在参与排队获取锁。 从概念上来说独占式对应只存在一个资源,且只能被一个线程或者说竞争者占用. 从概念上来说共享式对应存在多个资源的是有多个线程或者竞争者能够获取占用. 我们可以编写自己类继承AQS选择重写独占式或共享式模板方法,从而定义如何获取同步状态和释放同步状态的逻辑。 tryAcquire :尝试独占式获取同步状态,返回值为true则表示获取成功,否则获取失败。 tryRelease : 尝试独占式释放同步状态,返回值为true则表示获取成功,否则获取失败。 tryAcquireShared :尝试共享式获取同步状态,当返回值为大于等于0的时获得同步状态成功,否则获取失败。 tryReleaseShared :尝试共享式释放同步状态,返回值为true则表示获取成功,否则获取失败。 由于多个线程可以同时许可同时执行,当然我们选择使用共享同步,Sync需要重写 tryAcquire 获取同步状态条件逻辑, tryRelease 释放同步条件逻辑。其核心点在于使用同步状态做判断。当同状态为0时,许可被使用完了,同步状态大于0,许可被还可用,每次调用 tryAcquire 同步状态-1,每次调用 tryRelease 同步状态+1 内部存在有三个内部类 Sync、NonfairSync 和 FairSync 类。 Semaphore 很多方法都通过代理内部类的方法实现。 公平信号量获取许可 非公平信号量获取许可 释放许可 完整源码

Ras-Raf-MAPKK-MAPK信号转导通路

是RPTK介导的细胞信号转导,信号的级联放大过程。 受体酪氨酸激酶(receptor tyrosine kinases,RTKs) 包括6个亚族 信号转导:配体→受体→受体二聚化→受体的自磷酸化→ 激活RTK→胞内信号蛋白→启动信号传导  RTK- Ras信号通路: 配体→活化酪氨酸激酶RTK→活化的酪氨酸激酶RTK 结合接头蛋白adaptor → GRF(鸟苷酸释放因子)促进GDP释放→Ras(GTP结合蛋白)活化,诱导下游事件:Raf丝氨酸/苏氨酸蛋白激酶(又称MAPKKK)活化(使蛋白上的丝氨酸/苏氨酸残基磷酸化)→活化的Raf 结合并磷酸化另一种蛋白激酶MAPKK,导致MAPKK 活化(MAPKK是一种具双重特异的蛋白激酶,它能磷酸化MAPK的苏氨酸和酪氨酸残基使之激活)→MAPK活化→进入细胞核→其它激酶或基因调控蛋白(转录因子)的磷酸化修饰。G蛋白偶联受体介导的MAPK的激活MAPK(Mitogen-activated protein kinase)又称ERK(extracelular signal-regulated kinase)----真核细胞广泛存在的Ser/Thr蛋白激酶。 MAPK的底物:膜蛋白(受体、酶)、胞浆蛋白、核骨架蛋白、及多种核内或胞浆内的转录调控因子----在细胞增殖和分化中具有重要调控作用。 PTX敏感性G蛋白(Gi,Go)的亚基依赖于Ras激活MAPK,具体机制还有待深入研究; PKC、PLC与G蛋白偶联受体介导的MAPK激活 PKC和PLC 参与G蛋白偶联受体激活MAPK :  G蛋白偶联受体激活G蛋白; G蛋白亚基或 亚基激活PLC,促进膜磷脂代谢; 磷脂代谢产物( DAG + IP3 )激活PKC; PKC 通过Ras 或 Raf 激活MAPK ; 由于PKC对钙的依赖性不同,所以G蛋白偶联受体– MAPK途径对钙要 求不同; PKA对G蛋白偶联受体– MAPK途径的负调控 迄今未发现和制备出MAPK组成型突变(dominant negative mutant),提示细胞难于忍受MAPK的持续激活(MAPK的去活是细胞维持正常生长代谢所必须)。主要机制:特异性的Tyr/Thr磷脂酶可选择性地使MAPK去磷酸化,关闭MAPK信号。  cAMP , MAPK ;cAMP直接激活cAMP依赖的PKA;PKA可能通过RTK或通过抑制Raf-Ras相互作用起负调控作RTKs的失敏: 催化性受体的效应器位于受体本身,因此失敏即酶活性速发抑制。机制:受体的磷酸化修饰。EGF受体Thr654的磷酸化导致RTK活性的 抑制,如果该位点产生Ala突变,则阻止活性抑制,后又发现C 端的Ser1046/7也是磷酸化位点。磷酸化位点所在的C端恰好是 SH2蛋白的结合部位。引起受体磷酸化的激酶: PKC----作用于Thr654; CaMK2(Ca2+和CaM依赖的激酶2)----作用于Ser1046/7还发现:EGF受体是CDK的靶蛋白,提示和周期调控有关。 RTK晶体结构研究表明, RTK激活后形成稳定的非抑制性构象;磷酸化修饰后,形成抑制性构象,引起失敏。 RTK失敏对细胞正常功能所必须, RTK 的持续激活将导致细胞生长失控。

java中几种Map在什么情况下使用,并简单介绍原因及原理

HashMap 散列 线程不安全HashTable 由hashmap实现 有linklist 且线程安全ConcurrentHashMap 分段式锁机制的线程安全的Map单独业务 没有共享竞争 HashMap单独业务 并发不大 并对数据先后顺序有要求 可采用 HashTable高并发ConcurrentHashMap

Hashmap 桶内元素由链表转化为红黑树的条件

// 1. 最小树形化容量阈值:即 当哈希表中的容量 > 该值时,才允许树形化链表 (即 将链表 转换成红黑树) // 否则,若桶内元素太多时,则直接扩容,而不是树形化 // 为了避免进行扩容、树形化选择的冲突,这个值不能小于 4 * TREEIFY_THRESHOLD static final int MIN_TREEIFY_CAPACITY = 64; // 2. 桶的树化阈值:即 链表转成红黑树的阈值,在存储数据时,当链表长度 > 该值时,则将链表转换成红黑树 static final int TREEIFY_THRESHOLD = 8; // 3. 桶的链表还原阈值:即 红黑树转为链表的阈值,当在扩容(resize())时(此时HashMap的数据存储位置会重新计算),在重新计算存储位置后,当原有的红黑树内数量 < 6时,则将 红黑树转换成链表 static final int UNTREEIFY_THRESHOLD = 6;

用比喻的方法讲解一下 java 中 hashmap 的底层原理?

想象你有一个魔法箱子(HashMap),你可以把东西放进去,并且给每个东西贴上标签(键)以便稍后找到它们。箱子的内部是由一系列抽屉组成,每个抽屉都有一个唯一的标签(哈希码)。当你要放入一样东西时,首先你会生成一个标签(哈希码),这个标签会告诉你应该将东西放入哪个抽屉。假设你想放入一本书,并给它贴上标签 "科学书",然后根据这个标签(哈希码),你找到对应的抽屉并把书放进去。现在,如果你想找回这本书,你只需要记得它的标签 "科学书",然后根据这个标签(哈希码)再次找到对应的抽屉,从抽屉里拿出书来。这样你就能快速找到你之前放入箱子的东西。然而,有时候不同的东西可能会有相同的标签(哈希码),这就是所谓的哈希碰撞。在箱子内部,为了解决这个问题,每个抽屉都是一个链表,可以存放多个东西。当发生哈希碰撞时,新的东西会被添加到链表中,而不是新建一个抽屉。当箱子的负载(放入的东西数量)逐渐增加时,为了保持箱子的高效性能,箱子会自动增大,并重新调整抽屉的布局,确保箱子里的抽屉数量适合放入的东西的数量。这就是 Java 中 HashMap 的底层原理。它利用哈希函数将键映射到特定的索引位置,然后在该位置存储值。如果存在哈希碰撞,它会使用链表来处理冲突。当箱子内的东西越来越多时,箱子会自动调整大小,以保持高效性能。这种数据结构使得 HashMap 在大多数情况下能够快速查找和插入数据。

java中几种Map在什么情况下使用,并简单介绍原因及原理

Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复。所以通过指定的key就可以取出对应的value。Map接口定义了如下常用的方法:1、void clear():删除Map中所以键值对。2、boolean containsKey(Object key):查询Map中是否包含指定key,如果包含则返回true。3、boolean containsValue(Object value):查询Map中是否包含指定value,如果包含则返回true。4、Set entrySet():返回Map中所包含的键值对所组成的Set集合,每个集合元素都是Map.Entry对象(Entry是Map的内部类)。5、Object get(Object key):返回指定key所对应的value,如Map中不包含key则返回null。6、boolean isEmpty():查询Map是否为空,如果空则返回true。7、Set keySet():返回该Map中所有key所组成的set集合。8、Object put(Object key,Object value):添加一个键值对,如果已有一个相同的key值则新的键值对覆盖旧的键值对。9、void putAll(Map m):将指定Map中的键值对复制到Map中。10、Object remove(Object key):删除指定key所对应的键值对,返回可以所关联的value,如果key不存在,返回null。11、int size():返回该Map里的键值对的个数。12、Collection values():返回该Map里所有value组成的Collection。Map中包含一个内部类:Entry。该类封装了一个键值对,它包含了三个方法:1、Object getKey():返回该Entry里包含的key值。2、Object getValeu():返回该Entry里包含的value值。3、Object setValue(V value):设置该Entry里包含的value值,并返回新设置的value值。HashMap和Hashtable实现类:HashMap与HashTable的区别:1、 同步性:Hashtable是同步的,这个类中的一些方法保证了Hashtable中的对象是线程安全的。而HashMap则是异步的,因此HashMap中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用HashMap是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销,从而提高效率。2、 值:HashMap可以让你将空值作为一个表的条目的key或value,但是Hashtable是不能放入空值的。HashMap最多只有一个key值为null,但可以有无数多个value值为null。注意:1、用作key的对象必须实现hashCode和equals方法。2、不能保证其中的键值对的顺序3、尽量不要使用可变对象作为它们的key值。 LinkedHashMap: 它的父类是HashMap,使用双向链表来维护键值对的次序,迭代顺序与键值对的插入顺序保持一致。LinkedHashMap需要维护元素的插入顺序,so性能略低于HashMap,但在迭代访问元素时有很好的性能,因为它是以链表来维护内部顺序。TreeMap: Map接口派生了一个SortMap子接口,SortMap的实现类为TreeMap。TreeMap也是基于红黑树对所有的key进行排序,有两种排序方式:自然排序和定制排序。Treemap的key以TreeSet的形式存储,对key的要求与TreeSet对元素的要求基本一致。1、Map.Entry firstEntry():返回最小key所对应的键值对,如Map为空,则返回null。2、Object firstKey():返回最小key,如果为空,则返回null。3、Map.Entry lastEntry():返回最大key所对应的键值对,如Map为空,则返回null。4、Object lastKey():返回最大key,如果为空,则返回null。5、Map.Entry higherEntry(Object key):返回位于key后一位的键值对,如果为空,则返回null。6、Map.Entry lowerEntry(Object key):返回位于key前一位的键值对,如果为空,则返回null。7、Object lowerKey(Object key):返回位于key前一位key值,如果为空,则返回null。8、NavigableMap subMap(Object fromKey,boolean fromlnclusive,Object toKey,boolean toInciusive):返回该Map的子Map,其key范围从fromKey到toKey。9、SortMap subMap(Object fromKey,Object toKey );返回该Map的子Map,其key范围从fromkey(包括)到tokey(不包括)。10、SortMap tailMap(Object fromkey ,boolean inclusive):返回该Map的子Map,其key范围大于fromkey(是否包括取决于第二个参数)的所有key。11、 SortMap headMap(Object tokey ,boolean inclusive):返回该Map的子Map,其key范围小于tokey(是否包括取决于第二个参数)的所有key。WeakHashMap: WeakHashMap与HashMap的用法基本相同,区别在于:后者的key保留对象的强引用,即只要HashMap对象不被销毁,其对象所有key所引用的对象不会被垃圾回收,HashMap也不会自动删除这些key所对应的键值对对象。但WeakHashMap的key所引用的对象没有被其他强引用变量所引用,则这些key所引用的对象可能被回收。WeakHashMap中的每个key对象保存了实际对象的弱引用,当回收了该key所对应的实际对象后,WeakHashMap会自动删除该key所对应的键值对。 public static void main(String[] args) { // TODO Auto-generated method stub WeakHashMap w1=new WeakHashMap(); //添加三个键值对,三个key都是匿名字符串,没有其他引用 w1 .put("语文", "良好"); w1 .put("数学", "及格"); w1 .put("英语", "中等"); w1 .put("java", "good");//该key是一个系统缓存的字符串对象 System.out.println(w1 );//输出{java=good, 数学=及格, 英语=中等, 语文=良好} //通知系统进行垃圾回收 System.gc(); System.runFinalization(); System.out.println(w1 );//输出{java=good} }IdentityHashMap类:IdentityHashMap与HashMap基本相似,只是当两个key严格相等时,即key1==key2时,它才认为两个key是相等的 。IdentityHashMap也允许使用null,但不保证键值对之间的顺序。EnumMap类:1、EnumMap中所有key都必须是单个枚举类的枚举值,创建EnumMap时必须显示或隐式指定它对应的枚举类。2、EnumMap根据key的自然顺序,即枚举值在枚举类中定义的顺序,来维护键值对的次序。3、EnumMap不允许使用null作为key值,但value可以。

ARCMAP线合并怎么做

如果是同一图层,用shift选择两条线 ,merger如果是不用图层,用shift选择两条线 union

resultmap与resulttype有什么区别

使用mybatis进行数据库连接操作时对于SQL语句返回结果的处理通常有两种方式,一种就是resultType;另一种就是resultMap:1、resultType:当使用resultType做SQL语句返回结果类型处理时,对于SQL语句查询出的字段在相应的pojo中必须有和它相同的字段对应,而resultType中的内容就是pojo在本项目中的位置。因此对于单表查询的话用resultType是最合适的2、resultMap:当使用resultMap做SQL语句返回结果类型处理时,通常需要在mapper.xml中定义resultMap进行pojo和相应表字段的对应。resultMap对于一对一表连接的处理方式通常为在主表的pojo中添加嵌套另一个表的pojo,然后在mapper.xml中采用association节点元素进行对另一个表的连接处理3、resultType是直接表示返回类型的(对应着我们的model对象中的实体)resultMap则是对外部ResultMap的引用(提前定义了db和model之间的隐射key-->value关系),但是resultType跟resultMap不能同时存在。

关于Mybatis的mapper.xml文件中从pojo获取属性值的问题

在实际开发项目中,我们查询条件不可能很单一,查询字段可能包括很多字段,比如:查询条件可以有用户信息,商品信息,订单信息等。 这里我们的基础实体类是用户类,我在这个基础上扩展他,之后包装他作为我们的查询条件。 包装类:用于parameterType UserMapper接口 mapper配置文件编写sql: 上图中可看到在mapper.xml配置文件中用 userCustom.username 获取父类中的username私有成员变量,实际上是通过 userCustom.getUsername() 方法获得的. 以下文章通过一个简单的例子来看看ognl的用法 另还有一篇文章展示了mybatis中的ognl教程 通过以上的了解,现在把User类中的 getUsername 方法注释掉 再次运行程序,得到以下报错: 接着,我们仍旧保留对 getUsername 方法的注释,但是现在把 username 设置为 public 再次运行测试程序,得到以下正常的结果显示 以上就证明了在mapper.xml中, userCustom.username 实际上是通过调用了 userCustom.getUsername() 方法获得了user中的username属性,而不是userCustom直接访问父类User中的private修饰的username成员变量。

spring boot是一张表对应一个pojo类和一个mapper映射文件吗?

是的,可以通过mybitis的插件实现自动生成po,dao,mapper文件。

山下智久为什么叫YAMAP,是马上意思呢?

日文音译

Bim和Mcl-1在MAPK通路中的作用

抑菌。Bim和Mcl-1在MAPK通路中的作用最明显,感染的巨噬细胞凋亡率最高,抑菌作用最强。在炎症与细胞凋亡等应激反应中发挥重要作用。

山下智久的英文名为什么叫yamap

不是英文名,应该只算个昵称吧~至于原因上面解释的很清楚了~~拿了两分快速闪走~~~

mapgis这款软件的k9版本如何激活,求教学,谢谢!

我可以给你一份希望可以帮助你安装教程1、下载完毕后将ISO镜像文件加载到CD 驱动器,需要用到软碟通(ultraiso)。2、然后打开驱动器,打开MapGIS K9 证书服务文件夹,运行其中的ZDlccsvcInstall.exe开始安装许可服务。3、进入后开始全部都是默认,点击下一步,记得接受许可协议,然后选择安装类型,默认安装即可。4、在之后打开开始菜单中的许可证管理器,先点击安装服务,安装完毕点击启动服务。5、然后打开MapGIS K9 SP3文件夹,运行MapGISSetup.exe安装程序。6、接着接受协议,点击下一步,安装程序会检测需要的组件,如果没有点击下一步即可自动安装。7、接着选择安装路径。然后出现许可证服务器选择界面,选择本地许可证服务器。8、等待安装完毕。点击下载mapgis k9破解版

为什么有时候mapgis无法识别狗

打开任务管理器,查看zdLccSvc.exe进程有没有运行。如果没有说明你开机的时候没有自动运行证书服务,自然是不能识别狗的。需要手动启动服务,启动方法,我的电脑-服务-启动mapgis licence service。

怎么用GPS 经纬度去打开bing map?

BingMapsTask bingMapsTask = new BingMapsTask();//Omit the Center property to use the user"s current location.bingMapsTask.Center = new GeoCoordinate(52.1, 1.2); // Substitute for your lat/longbingMapsTask.Show();

我用xilinx ise到Implement的map这一步出现了一下16个错误,求解决办法(字数限制,无办法粘贴所有错误)

用 synplify综合就好了,Xilinx自己的编译器做的太差了

帮忙把SMAP的《Mermaid》的汉字标注上平假名吧~~个人好想唱这首歌啊,罗马音神马的就不用了……

谁(だれ)とも违(ちが)う君(きみ)だから もっと知(し)りたいのさ 见(み)えない心(こころ)の影(かげ)も 见(み)えそうな灯(あか)りもあふれる想(おも)いこぼれて 抱(かか)えきれないなら不器用(ぶきよう)でも仆(ぼく)なりに ぎゅっと手(て)を握(にぎ)るんだ见(み)つめるよ ただひとつ 君(きみ)がカタチにしていくものが二度(にど)と来(こ)ない 「今(いま)」に键(かぎ)をかけるからたぎる仆(ぼく)の胸(むね)の水面(すいめん)に 踊(おど)る君(きみ)はそうMermaid时间(とき)の流(なが)れを止(と)める このgood feeling!愿(ねが)う君(きみ)の期待(きたい)に応(こた)え 笑(わら)える仆()になるよこれからも今(いま)以上(いじょう)によろしくスローモーションで感(かん)じて 噛(か)み缔めていたいのさつまらない诱惑(ゆうわく)なら とうに振(ふ)り切(き)ってるんだ途切(とぎ)れ途切(とぎ)れの声(こえ)でも 波(なみ)を打(う)つ鼓动(こどう)さ仆(ぼく)が受(う)け止(と)めたいから そして伝(つた)えるから息(いき)をつくタイミングで 果(は)てしない道程(どうてい)のgame of love情热(じょうねつ)を重(かさ)ねて大人(おとな)になるよ騒(さわ)ぐ仆(ぼく)の胸(むね)の隙间(すきま)に 揺(ゆ)れる君(きみ)はそうMermaid声(こえ)が届(とど)いて响(ひび)くまでずっとcalling!早足(はやあし)の街(まち)を追(お)いかけて 踬いて転(ころ)んでも仆(ぼく)だけはずっとそばにいるから寄(よ)り添(そ)い歩(ある)く それだけじゃ伝(つた)わらないふたりの明日(あした)を一歩(いっぽ)一(いち)歩(ほ) 歩幅(ほはば)あわそうたぎる仆(ぼく)の胸(むね)の水面(すいめん)に 踊(おど)る君(きみ)はそうMermaid时间の流(なが)れを止(と)める このgood feeling!君(きみ)の悲(かな)しみ全部(ぜんぶ)抱(かか)え 笑(わら)える仆()になるよこれからも今(いま)以上(いじょう)によろしく

echarts 的tooltip在做省市联动的china-map的时候怎么在鼠标移到div最右侧时自动移到鼠标的左边

给这个DIV的样式加一条:cursor:pointer;

Echarts控制map的tooltip显示或隐藏

u2003u2003功能需求:根据当前用户权限,控制地图只高亮显示某一个区域的信息,其他区域置为背景色并且鼠标事件不响应。 u2003u2003首先尝试分级设置,先在option级tooltip设置不显示,然后在geo的regions高亮显示的每个项设置tooptip显示,结果显示Echarts并不像css那样支持优先级覆盖,或者说option级设置的权限最高。 u2003u2003基于文档说明,能通过事件动态显示tooltip组件: u2003u20031. 禁止echarts的默认事件触发 u2003u20032. 自定义事件响应 。mouseover触发 show ,在这加入相应的条件判断就能实现动态响应了,单要注意的是,需要根据情况选择特定的方式,这里我用的是方式二,因为我地图是基于series-map进行的创建虽然在series当中设置了geoIndex,但测试后发现之后方式二才能正常响应;mouseout触发 hide

mapogo males啥意思

  Mapogo males意思:狮子联盟。  Mapogo males是一个联盟:  狮子联盟  联盟中文名:坏男孩联盟  联盟英文名:Mapogo males  联盟数量:6只  联盟首领:老大-恩格拉拉里克  所在地区:萨比森私人保护区(Sabi Sands game reserve),克鲁格国家公园(Kruger national park)  相关狮群:斯巴达狮群(Eyrefield/Sparta Pride),查拉拉狮群(Tsalala Pride),卡斯尔顿狮群(Castleton Pride),史迪克斯狮群(Styx pride),赛姆万尼亚狮群(Ximunvanyane Pride),欧萨瓦狮群(Othawa Pride),森德河狮群(Sand river pride)等很多狮群  联盟成员出生时间:老大出生于1998年10月  老二和老三出生于2001年1月  老四出生于2001年3月  老五和老六出生于2001年11月  联盟介绍:近年来萨比森保护区内的狮子都遭受到了黑暗的压迫,日子过的十分艰苦,而造成这一切的是一个由6只雄狮所组成的雄狮联盟。有人说他们是恶魔的化身,也有人说他们只是一群无恶不作的恶棍,更有人说他们是审判者。人们称他们为“坏男孩联盟”,然而无论传闻中的他们是多么的可怕,当你深入了解了他们后便会发现,即使是“恶棍”也会有感人至深的一面。

英文句子中可不可以没有动词?比如:the map on the table

这不是一个完整的句子,句子是要有动词的,如be动词,实义动词等

环境映射(EnvironmentMapping)的立方映射

立方环境映射(Cubic Environment Mapping)立方环境映射是现在常用环境映射技术。我们知道游戏场景中经常通过在一个正方体上的六个面贴上前后左右上下六个贴图来模拟天空、宇宙等环境,称为Cubemap有的引擎中成为Skybox,立方环境映射的原理就是在游戏中所需要产生映射的物体的位置动态生成一套Cubemap,再对Cubemap进行采样生成物体表面应该反射出的周遭环境。具体的采样方法是利用物体表面的法线来计算的,我们假设动态生成的Cubemap的正方体刚刚好包围住需要产生环境映射效果的物体,我们从摄像机也就是观察点出发同物体表面产生出的反射向量(同Phong光照模型的镜面反射中的反射向量是相同的,计算方法也相同R=2(E*N)*N-E),这个反射向量同正方体相交于一点,得到了这个点的所在面及UV坐标,采样,得到的颜色值就是我们应当看到。立方环境映射的原理就是这样的,但是这些计算步骤并不需要我们在使用的时候过多考虑,因为从Cubemap的生成,到采样的计算,图形API已经都为我们封装好了,下面记录了在DirectX中简单的API调用流程,权作笔记。 首先需要声明Cubemap的贴图LPDIRECT3DCUBETEXTURE9 m_pCubeMap = NULL;然后创建Cubemap贴图pd3dDevice->CreateCubeTexture(256,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT , &m_pCubeMap,NULL );注意这里用到了D3DUSAGE_RENDERTARGET,也就是说我们的Cubemap需要靠RenderTarget绘制。如果需要的话,深度缓冲也可以考虑在内。IDirect3DSurface9* g_pDepthCube = NULL;DXUTDeviceSettings d3dSettings = DXUTGetDeviceSettings();pd3dDevice->CreateDepthStencilSurface( 256, 256, d3dSettings.pp.AutoDepthStencilFormat,D3DMULTISAMPLE_NONE,0,TRUE,&g_pDepthCube, NULL );绘制函数void RenderSceneIntoCubeMap( IDirect3DDevice9 *pd3dDevice, double fTime ){HRESULT hr;// Cubemap使用的投影矩阵D3DXMATRIXA16 mProj;D3DXMatrixPerspectiveFovLH( &mProj, D3DX_PI * 0.5f, 1.0f, 0.01f, 100.0f );LPDIRECT3DSURFACE9 pRTOld = NULL;V( pd3dDevice->GetRenderTarget( 0, &pRTOld ) );LPDIRECT3DSURFACE9 pDSOld = NULL;//if( SUCCEEDED( pd3dDevice->GetDepthStencilSurface( &pDSOld ) ) )//{// // 如果使用深度缓冲// V( pd3dDevice->SetDepthStencilSurface( g_pDepthCube ) );//}for( int nFace = 0; nFace < 6; ++nFace ) //依次完成Cubemap中的六个面的绘制{LPDIRECT3DSURFACE9 pSurf;V( m_pCubeMap->GetCubeMapSurface( (D3DCUBEMAP_FACES)nFace, 0, &pSurf ) );V( pd3dDevice->SetRenderTarget( 0, pSurf ) );SAFE_RELEASE( pSurf );D3DXMATRIXA16 mView = DXUTGetCubeMapViewMatrix( nFace );V( pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER,0x000000ff, 1.0f, 0L ) );pd3dDevice->SetTransform(D3DTS_VIEW,&mView);pd3dDevice->SetTransform(D3DTS_PROJECTION,&mProj);if( SUCCEEDED( pd3dDevice->BeginScene() ) ){//在这里绘制环境pd3dDevice->EndScene();}}// Restore depth-stencil buffer and render target/*if( pDSOld )//如果使用深度缓冲{V( pd3dDevice->SetDepthStencilSurface( pDSOld ) );SAFE_RELEASE( pDSOld );}*/V( pd3dDevice->SetRenderTarget( 0, pRTOld ) );SAFE_RELEASE( pRTOld );}这个绘制函数一般在每一帧绘制场景的最开始执行,先将场景内的物体绘制在Cubemap上。这样我们就有了可用的Cubemap,之后我们绘制需要采用环境映射的物体时,将这个Cubemap作为Texture传入Shader内,另外还需传入观察向量用于计算反射向量。在Shader中,顶点着色器中完成反射向量的计算:float3 vecReflect = normalize(reflect(vecEye, InNormal));像素着色器负责采样,HLSL中已经有现成的函数可以使用,我们只需将计算所得反射向量传入即可。Output.RGBColor = texCUBE(EnvironmentSampler, In.CubeTexcoord);采样器EnvironmentSampler并不需要特别的设置。texture EnvironmentMap;samplerCUBE EnvironmentSampler = sampler_state{Texture = (EnvironmentMap);MipFilter = LINEAR;MinFilter = LINEAR;MagFilter = LINEAR;};

maple中的subs()函数是什么意思?怎么用

基本初等函数:绝对值 abs、开方sqrt、以e为底指数exp、log、ln、log10、sin、cos、tan、cot、sec、csc、反三角 arc、双曲sh,ch,th,cth、反双曲 arc 等。具体函数使用方法请参考官网资料:http://www.mathsoft.cc/shiyongjiqiao/hanshu-mingling.html

点P在∠MAN内部,现有四个等式:使∠MAP=∠NAP,∠PAN=12∠MAN,∠MAP=12∠MAN,∠MAN=2∠MAP,其中能表

解答:解:如图:根据角平分线定义可得四个等式:①∠MAP=∠NAP,②∠PAN=12∠MAN,③∠MAP=12∠MAN,④∠MAN=2∠MAP,都正确;故答案为四.

②点P在∠MAN内部,现有四个等式:①∠PAM=∠NAP;②∠PAN=1/2∠MAN;③∠MAP=1/2∠MAN;④∠MAN=2∠MAP。

B

②点P在∠MAN内部,现有四个等式:①∠PAM=∠NAP;②∠PAN=1/2∠MAN;③∠MAP=1/2∠MAN;④∠MAN=2∠MAP。

D

点P在∠MAN的内部,现有4个等式:①∠PAM=∠NAP;②∠PAN=1/2∠MAN;③∠MAP=

分析:利用角平分线的定义计算.解答:解:根据角平分线的定义可知:均对.故选D.点评:本题考查角平分线的定义.

点P在∠MAN内部,现有四个等式:①∠PAM=∠PAN,②∠PAN=12∠MAN,③∠MAP=12∠MAN④∠MAN=2∠MAP,其中

解;如图:根据角平分线定义可得四个等式:①∠PAM=∠PAN,②∠PAN=12∠MAN,③∠MAP=12∠MAN④∠MAN=2∠MAP都正确;故选:D.

魔兽地图修改怎么导入war3map.wts文件,不会的别答

把格式修改成魔兽地图化

为什么java中Hashmap 实例查看不到成员变量

jre编译成这样了

前端的mapping用java怎么写

在Java中,可以使用Spring框架来实现前端路由。具体步骤如下:1、在SpringBoot项目中引入spring-web模块和spring-webmvc模块。2、在SpringBoot的启动类中添加注解`@EnableWebMvc`,开启SpringMVC的自动配置。3、创建一个Controller类,添加注解`@Controller`,用于处理前端请求。4、在Controller类中添加方法,并使用注解`@RequestMapping`来指定URL路径。5、创建对应的HTML页面,并放置在resources/templates目录下。6、配置模板引擎,使得Spring能够正确解析HTML模板。

为什么网上那些java视频讲集合框架都只讲arraylist,set,hashmap。其他集合都不

做java开发,用的最多的结合框架,就这么几个,关于别的集合框架,一是用的不多,二是,你要是真想学这些东西,你应该去学习下,数据结构,而不是去学java的API,你懂大概原理的时候,需要用的时候,你去找API就行了,空学API实际上用处不大

Java HashMap 复杂度的问题

第一个是O(n),因为是遍历整个集合 ,第二个是O(m*n),看他们提供的源码实现就可知道,两重for循环

急!!!java集合hashMap问题,高手请帮忙

这样理解:因为数组是引用型,test3 = hash_arrayHashSets[0];test3已经指向hash_arrayHashSets[0]这个实体, test3.add("c"),会在hash_arrayHashSets[0]增加一个元素“C”,这样实体hash_arrayHashSets[0]已经改变了。

ArrayList和Vector的区别是什么?HashMap和Hashtable的区别呢?

ArrayList和Vector都实现了List接口,我们可以分析其源代码,很容易找出它们的区别:Vector中的add方法如下:publicsynchronizedbooleanadd(Ee){}ArrayList中的add方法如下:publicbooleanadd(Ee)很显然区别就在于一个有synchronized即线程同步,而另一外没有,参考源代码你会发现绝大部分方法都是这样的。也就是说当存在多线程访问时,Vector比ArrayList要安全,但这种安全的代价就是要付出更多的系统性能一般情况下我们是使用ArrayList,因为存在多线程去访问同一个list对象的可能性并不是太多。对于HashMap和Hashtable原理是一样的,Hashtable实现了线程同步,能确保多线程访问时的安全性,性能要比hashMap低

HashMap为什么不安全?

1、HashMap线程不安全原因: 原因: JDK1.7 中,由于多线程对HashMap进行扩容,调用了HashMap#transfer (),具体原因:某个线程执行过程中,被挂起,其他线程已经完成数据迁移,等CPU资源释放后被挂起的线程重新执行之前的逻辑,数据已经被改变,造成死循环、数据丢失。

HashMap和HashSet的区别

1 HashMap和HashSet的区别是Java面试中最常被问到的问题。如果没有涉及到Collection框架以及多线程的面试,可以说是不完整。而Collection框架的问题不涉及到HashSet和HashMap,也可以说是不完整。HashMap和HashSet都是collection框架的一部分,它们让我们能够使用对象的集合。collection框架有自己的接口和实现,主要分为Set接口,List接口和Queue接口。它们有各自的特点,Set的集合里不允许对象有重复的值,List允许有重复,它对集合中的对象进行索引,Queue的工作原理是FCFS算法(First Come, First Serve)。23 首先让我们来看看什么是HashMap和HashSet,然后再来比较它们之间的分别。4 什么是HashSet56 HashSet实现了Set接口,它不允许集合中有重复的值,当我们提到HashSet时,第一件事情就是在将对象存储在HashSet之前,要先确保对象重写equals()和hashCode()方法,这样才能比较对象的值是否相等,以确保set中没有储存相等的对象。如果我们没有重写这两个方法,将会使用这个方法的默认实现。78 public boolean add(Object o)方法用来在Set中添加元素,当元素值重复时则会立即返回false,如果成功添加的话会返回true。9 什么是HashMap10 11 HashMap实现了Map接口,Map接口对键值对进行映射。Map中不允许重复的键。Map接口有两个基本的实现,HashMap和TreeMap。TreeMap保存了对象的排列次序,而HashMap则不能。HashMap允许键和值为null。HashMap是非synchronized的,但collection框架提供方法能保证HashMap synchronized,这样多个线程同时访问HashMap时,能保证只有一个线程更改Map。12 13 public Object put(Object Key,Object value)方法用来将元素添加到map中。14 15 你可以阅读这篇文章看看HashMap的工作原理,以及这篇文章看看HashMap和HashTable的区别。16 HashSet和HashMap的区别17 *HashMap* *HashSet*18 HashMap实现了Map接口 HashSet实现了Set接口19 HashMap储存键值对 HashSet仅仅存储对象20 使用put()方法将元素放入map中 使用add()方法将元素放入set中21 HashMap中使用键对象来计算hashcode值 HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false22 HashMap比较快,因为是使用唯一的键来获取对象 HashSet较HashMap来说比较慢

ConcurrentHashMap 弱一致的迭代器 是什么原理

concurrenthashmap是弱一致的,iterator 都是弱一致性的,两者的迭代器的一致性不同的。当删除了第7个元素的时候,B会感知到已删除,所以B的后续迭代都是真实的数据。

hashmap 为什么线程不安全

一直以来只是知道HashMap是线程不安全的,但是到底HashMap为什么线程不安全,多线程并发的时候在什么情况下可能出现问题?HashMap底层是一个Entry数组,当发生hash冲突的时候,hashmap是采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。javadoc中关于hashmap的一段描述如下:此实现不是同步的。如果多个线程同时访问一个哈希映射,而其中至少一个线程从结构上修改了该映射,则它必须 保持外部同步。(结构上的修改是指添加或删除一个或多个映射关系的任何操作;仅改变与实例已经包含的键关联的值不是结构上的修改。)这一般通过对自然封装该映射的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedMap 方法来“包装”该映射。最好在创建时完成这一操作,以防止对映射进行意外的非同步访问,如下所示: Map m = Collections.synchronizedMap(new HashMap(...));1、[java] view plain copyvoid addEntry(int hash, K key, V value, int bucketIndex) { Entry<K,V> e = table[bucketIndex]; table[bucketIndex] = new Entry<K,V>(hash, key, value, e); if (size++ >= threshold) resize(2 * table.length); } 在hashmap做put操作的时候会调用到以上的方法。现在假如A线程和B线程同时对同一个数组位置调用addEntry,两个线程会同时得到现在的头结点,然后A写入新的头结点之后,B也写入新的头结点,那B的写入操作就会覆盖A的写入操作造成A的写入操作丢失2、[java] view plain copyfinal Entry<K,V> removeEntryForKey(Object key) { int hash = (key == null) ? 0 : hash(key.hashCode()); int i = indexFor(hash, table.length); Entry<K,V> prev = table[i]; Entry<K,V> e = prev; while (e != null) { Entry<K,V> next = e.next; Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { modCount++; size--; if (prev == e) table[i] = next; else prev.next = next; e.recordRemoval(this); return e; } prev = e; e = next; } return e; } 删除键值对的代码如上:当多个线程同时操作同一个数组位置的时候,也都会先取得现在状态下该位置存储的头结点,然后各自去进行计算操作,之后再把结果写会到该数组位置去,其实写回的时候可能其他的线程已经就把这个位置给修改过了,就会覆盖其他线程的修改3、addEntry中当加入新的键值对后键值对总数量超过门限值的时候会调用一个resize操作,代码如下:[java] view plain copyvoid resize(int newCapacity) { Entry[] oldTable = table; int oldCapacity = oldTable.length; if (oldCapacity == MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return; } Entry[] newTable = new Entry[newCapacity]; transfer(newTable); table = newTable; threshold = (int)(newCapacity * loadFactor); } 这个操作会新生成一个新的容量的数组,然后对原数组的所有键值对重新进行计算和写入新的数组,之后指向新生成的数组。当多个线程同时检测到总数量超过门限值的时候就会同时调用resize操作,各自生成新的数组并rehash后赋给该map底层的数组table,结果最终只有最后一个线程生成的新数组被赋给table变量,其他线程的均会丢失。而且当某些线程已经完成赋值而其他线程刚开始的时候,就会用已经被赋值的table作为原始数组,这样也会有问题。

hashtable和hashmap有什么区别,共同之处?、

该题可以在baidu ,有很多解答.我这需要说明下 这个是面试常 问的但hashtable 基本被淘汰了 ,可用concurrentMap 替代

java 中的hashmap如何解决冲突?就是如何保证两个不同的object放到hashmap中,计算key值时没有问题?

大概是不同的object计算出的hascode不同

Java中HashMap和TreeMap的区别深入理解

两者都是非线程安全,前者无排序,后者会自动排序

ConcurrentHashMap 弱一致的迭代器 是什么原理

ConcurrentHashMap的弱一致性主要是为了提升效率,是一致性与效率之间的一种权衡。要成为强一致性,就得到处使用锁,甚至是全局锁,这就与Hashtable和同步的HashMap一样了。

java7和java8对hashmap做了哪些优化

HashMap的原理介绍x0dx0ax0dx0a此乃老生常谈,不作仔细解说。x0dx0a一句话概括之:HashMap是一个散列表,它存储的内容是键值对(key-value)映射。x0dx0ax0dx0aJava 7 中HashMap的源码分析x0dx0ax0dx0a首先是HashMap的构造函数代码块1中,根据初始化的Capacity与loadFactor(加载因子)初始化HashMap.x0dx0a//代码块1x0dx0a public HashMap(int initialCapacity, float loadFactor) {x0dx0a if (initialCapacity < 0)x0dx0a throw new IllegalArgumentException("Illegal initial capacity: " +x0dx0a initialCapacity);x0dx0a if (initialCapacity > MAXIMUM_CAPACITY)x0dx0a initialCapacity = MAXIMUM_CAPACITY;x0dx0a if (loadFactor <= 0 || Float.isNaN(loadFactor))x0dx0a throw new IllegalArgumentException("Illegal load factor: " +loadFactor);x0dx0ax0dx0a this.loadFactor = loadFactor;x0dx0a threshold = initialCapacity;x0dx0a init();x0dx0a }x0dx0ax0dx0aJava7中对于的put方法实现相对比较简单,首先根据 key1 的key值计算hash值,再根据该hash值与table的length确定该key所在的index,如果当前位置的Entry不为null,则在该Entry链中遍历,如果找到hash值和key值都相同,则将值value覆盖,返回oldValue;如果当前位置的Entry为null,则直接addEntry。x0dx0a代码块2x0dx0apublic V put(K key, V value) {x0dx0a if (table == EMPTY_TABLE) {x0dx0a inflateTable(threshold);x0dx0a }x0dx0a if (key == null)x0dx0a return putForNullKey(value);x0dx0a int hash = hash(key);x0dx0a int i = indexFor(hash, table.length);x0dx0a for (Entry e = table[i]; e != null; e = e.next) {x0dx0a Object k;x0dx0a if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {x0dx0a V oldValue = e.value;x0dx0a e.value = value;x0dx0a e.recordAccess(this);x0dx0a return oldValue;x0dx0a }x0dx0a }x0dx0ax0dx0a modCount++;x0dx0a addEntry(hash, key, value, i);x0dx0a return null;x0dx0a }x0dx0ax0dx0a//addEntry方法中会检查当前table是否需要resizex0dx0a void addEntry(int hash, K key, V value, int bucketIndex) {x0dx0a if ((size >= threshold) && (null != table[bucketIndex])) {x0dx0a resize(2 * table.length); //当前map中的size 如果大于threshole的阈值,则将resize将table的length扩大2倍。x0dx0a hash = (null != key) ? hash(key) : 0;x0dx0a bucketIndex = indexFor(hash, table.length);x0dx0a }x0dx0ax0dx0a createEntry(hash, key, value, bucketIndex);x0dx0a }x0dx0ax0dx0aJava7 中resize()方法的实现比较简单,将OldTable的长度扩展,并且将oldTable中的Entry根据rehash的标记重新计算hash值和index移动到newTable中去。代码如代码块3中所示,x0dx0a//代码块3 --JDK7中HashMap.resize()方法x0dx0avoid resize(int newCapacity) {x0dx0a Entry[] oldTable = table;x0dx0a int oldCapacity = oldTable.length;x0dx0a if (oldCapacity == MAXIMUM_CAPACITY) {x0dx0a threshold = Integer.MAX_VALUE;x0dx0a return;x0dx0a }x0dx0ax0dx0a Entry[] newTable = new Entry[newCapacity];x0dx0a transfer(newTable, initHashSeedAsNeeded(newCapacity));x0dx0a table = newTable;x0dx0a threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);x0dx0a }x0dx0ax0dx0a /**x0dx0a * 将当前table的Entry转移到新的table中x0dx0a */x0dx0a void transfer(Entry[] newTable, boolean rehash) {x0dx0a int newCapacity = newTable.length;x0dx0a for (Entry e : table) {x0dx0a while(null != e) {x0dx0a Entry next = e.next;x0dx0a if (rehash) {x0dx0a e.hash = null == e.key ? 0 : hash(e.key);x0dx0a }x0dx0a int i = indexFor(e.hash, newCapacity);x0dx0a e.next = newTable[i];x0dx0a newTable[i] = e;x0dx0a e = next;x0dx0a }x0dx0a }x0dx0a }x0dx0ax0dx0aHashMap性能的有两个参数:初始容量(initialCapacity) 和加载因子(loadFactor)。容量 是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。x0dx0a根据源码分析可以看出:在Java7 中 HashMap的entry是按照index索引存储的,遇到hash冲突的时候采用拉链法解决冲突,将冲突的key和value插入到链表list中。x0dx0a然而这种解决方法会有一个缺点,假如key值都冲突,HashMap会退化成一个链表,get的复杂度会变成O(n)。x0dx0a在Java8中为了优化该最坏情况下的性能,采用了平衡树来存放这些hash冲突的键值对,性能由此可以提升至O(logn)。x0dx0a代码块4 -- JDK8中HashMap中常量定义x0dx0a static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; x0dx0a static final int TREEIFY_THRESHOLD = 8; // 是否将list转换成tree的阈值x0dx0a static final int UNTREEIFY_THRESHOLD = 6; // 在resize操作中,决定是否untreeify的阈值x0dx0a static final int MIN_TREEIFY_CAPACITY = 64; // 决定是否转换成tree的最小容量x0dx0a static final float DEFAULT_LOAD_FACTOR = 0.75f; // default的加载因子x0dx0ax0dx0a在Java 8 HashMap的put方法实现如代码块5所示,x0dx0a代码块5 --JDK8 HashMap.put方法x0dx0a public V put(K key, V value) {x0dx0a return putVal(hash(key), key, value, false, true);x0dx0a }x0dx0ax0dx0a final V putVal(int hash, K key, V value, boolean onlyIfAbsent,x0dx0a boolean evict) {x0dx0a Node[] tab; Node p; int n, i;x0dx0a if ((tab = table) == null || (n = tab.length) == 0)x0dx0a n = (tab = resize()).length; //table为空的时候,n为table的长度x0dx0a if ((p = tab[i = (n - 1) & hash]) == null)x0dx0a tab[i] = newNode(hash, key, value, null); // (n - 1) & hash 与Java7中indexFor方法的实现相同,若i位置上的值为空,则新建一个Node,table[i]指向该Node。x0dx0a else {x0dx0a // 若i位置上的值不为空,判断当前位置上的Node p 是否与要插入的key的hash和key相同x0dx0a Node e; K k;x0dx0a if (p.hash == hash &&x0dx0a ((k = p.key) == key || (key != null && key.equals(k))))x0dx0a e = p;//相同则覆盖之x0dx0a else if (p instanceof TreeNode)x0dx0a // 不同,且当前位置上的的node p已经是TreeNode的实例,则再该树上插入新的node。x0dx0a e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);x0dx0a else {x0dx0a // 在i位置上的链表中找到p.next为null的位置,binCount计算出当前链表的长度,如果继续将冲突的节点插入到该链表中,会使链表的长度大于tree化的阈值,则将链表转换成tree。x0dx0a for (int binCount = 0; ; ++binCount) {x0dx0a if ((e = p.next) == null) {x0dx0a p.next = newNode(hash, key, value, null);x0dx0a if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1stx0dx0a treeifyBin(tab, hash);x0dx0a break;x0dx0a }x0dx0a if (e.hash == hash &&x0dx0a ((k = e.key) == key || (key != null && key.equals(k))))x0dx0a break;x0dx0a p = e;x0dx0a }x0dx0a }x0dx0a if (e != null) { // existing mapping for keyx0dx0a V oldValue = e.value;x0dx0a if (!onlyIfAbsent || oldValue == null)x0dx0a e.value = value;x0dx0a afterNodeAccess(e);x0dx0a return oldValue;x0dx0a }x0dx0a }x0dx0a ++modCount;x0dx0a if (++size > threshold)x0dx0a resize();x0dx0a afterNodeInsertion(evict);x0dx0a return null;x0dx0a }x0dx0ax0dx0a再看下resize方法,由于需要考虑hash冲突解决时采用的可能是list 也可能是balance tree的方式,因此resize方法相比JDK7中复杂了一些,x0dx0a代码块6 -- JDK8的resize方法x0dx0a inal Node[] resize() {x0dx0a Node[] oldTab = table;x0dx0a int oldCap = (oldTab == null) ? 0 : oldTab.length;x0dx0a int oldThr = threshold;x0dx0a int newCap, newThr = 0;x0dx0a if (oldCap > 0) {x0dx0a if (oldCap >= MAXIMUM_CAPACITY) {x0dx0a threshold = Integer.MAX_VALUE;//如果超过最大容量,无法再扩充tablex0dx0a return oldTab;x0dx0a }x0dx0a else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&x0dx0a oldCap >= DEFAULT_INITIAL_CAPACITY)x0dx0a newThr = oldThr << 1; // threshold门槛扩大至2倍x0dx0a }x0dx0a else if (oldThr > 0) // initial capacity was placed in thresholdx0dx0a newCap = oldThr;x0dx0a else { // zero initial threshold signifies using defaultsx0dx0a newCap = DEFAULT_INITIAL_CAPACITY;x0dx0a newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);x0dx0a }x0dx0a if (newThr == 0) {x0dx0a float ft = (float)newCap * loadFactor;x0dx0a newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?x0dx0a (int)ft : Integer.MAX_VALUE);x0dx0a }x0dx0a threshold = newThr;x0dx0a @SuppressWarnings({"rawtypes","unchecked"})x0dx0a Node[] newTab = (Node[])new Node[newCap];// 创建容量为newCap的newTab,并将oldTab中的Node迁移过来,这里需要考虑链表和tree两种情况。

hashmap为什么不是线程安全的

首页所有文章资讯Web架构基础技术书籍教程Java小组工具资源谈谈HashMap线程不安全的体现2016/10/18|分类:基础技术|6条评论|标签:HASHMAP,并发分享到:26原文出处:HoseeHashMap的原理以及如何实现,之前在JDK7与JDK8中HashMap的实现中已经说明了。那么,为什么说HashMap是线程不安全的呢?它在多线程环境下,会发生什么情况呢?1.resize死循环我们都知道HashMap初始容量大小为16,一般来说,当有数据要插入时,都会检查容量有没有超过设定的thredhold,如果超过,需要增大Hash表的尺寸,但是这样一来,整个Hash表里的元素都需要被重算一遍。这叫rehash,这个成本相当的大。voidresize(intnewCapacity){Entry[]oldTable=table;intoldCapacity=oldTable.length;if(oldCapacity==MAXIMUM_CAPACITY){threshold=Integer.MAX_VALUE;return;}Entry[]newTable=newEntry[newCapacity];transfer(newTable,initHashSeedAsNeeded(newCapacity));table=newTable;threshold=(int)Math.min(newCapacity*loadFactor,MAXIMUM_CAPACITY+1);}voidtransfer(Entry[]newTable,booleanrehash){intnewCapacity=newTable.length;for(Entrye:table){while(null!=e){Entrynext=e.next;if(rehash){e.hash=null==e.key?0:hash(e.key);}inti=indexFor(e.hash,newCapacity);e.next=newTable[i];newTable[i]=e;e=next;}}}大概看下transfer:对索引数组中的元素遍历对链表上的每一个节点遍历:用next取得要转移那个元素的下一个,将e转移到新Hash表的头部,使用头插法插入节点。循环2,直到链表节点全部转移循环1,直到所有索引数组全部转移经过这几步,我们会发现转移的时候是逆序的。假如转移前链表顺序是1->2->3,那么转移后就会变成3->2->1。这时候就有点头绪了,死锁问题不就是因为1->2的同时2->1造成的吗?所以,HashMap的死锁问题就出在这个transfer()函数上。

Hashpmap的原理,HashMap怎样保证key的唯一性

去看看这个帖子吧,或许对你有所帮助http://www.cnblogs.com/yxysuanfa/p/6932010.html

java7和java8对hashmap做了哪些优化

HashMap的原理介绍此乃老生常谈,不作仔细解说。一句话概括之:HashMap是一个散列表,它存储的内容是键值对(key-value)映射。Java 7 中HashMap的源码分析首先是HashMap的构造函数代码块1中,根据初始化的Capacity与loadFactor(加载因子)初始化HashMap.//代码块1 public HashMap(int initialCapacity, float loadFactor) { if (initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity); if (initialCapacity > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; if (loadFactor <= 0 || Float.isNaN(loadFactor)) throw new IllegalArgumentException("Illegal load factor: " +loadFactor); this.loadFactor = loadFactor; threshold = initialCapacity; init(); }Java7中对于<key1,value1>的put方法实现相对比较简单,首先根据 key1 的key值计算hash值,再根据该hash值与table的length确定该key所在的index,如果当前位置的Entry不为null,则在该Entry链中遍历,如果找到hash值和key值都相同,则将值value覆盖,返回oldValue;如果当前位置的Entry为null,则直接addEntry。代码块2public V put(K key, V value) { if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null) return putForNullKey(value); int hash = hash(key); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }//addEntry方法中会检查当前table是否需要resize void addEntry(int hash, K key, V value, int bucketIndex) { if ((size >= threshold) && (null != table[bucketIndex])) { resize(2 * table.length); //当前map中的size 如果大于threshole的阈值,则将resize将table的length扩大2倍。 hash = (null != key) ? hash(key) : 0; bucketIndex = indexFor(hash, table.length); } createEntry(hash, key, value, bucketIndex); }Java7 中resize()方法的实现比较简单,将OldTable的长度扩展,并且将oldTable中的Entry根据rehash的标记重新计算hash值和index移动到newTable中去。代码如代码块3中所示,//代码块3 --JDK7中HashMap.resize()方法void resize(int newCapacity) { Entry[] oldTable = table; int oldCapacity = oldTable.length; if (oldCapacity == MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return; } Entry[] newTable = new Entry[newCapacity]; transfer(newTable, initHashSeedAsNeeded(newCapacity)); table = newTable; threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1); } /** * 将当前table的Entry转移到新的table中 */ void transfer(Entry[] newTable, boolean rehash) { int newCapacity = newTable.length; for (Entry<K,V> e : table) { while(null != e) { Entry<K,V> next = e.next; if (rehash) { e.hash = null == e.key ? 0 : hash(e.key); } int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } } }HashMap性能的有两个参数:初始容量(initialCapacity) 和加载因子(loadFactor)。容量 是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。根据源码分析可以看出:在Java7 中 HashMap的entry是按照index索引存储的,遇到hash冲突的时候采用拉链法解决冲突,将冲突的key和value插入到链表list中。然而这种解决方法会有一个缺点,假如key值都冲突,HashMap会退化成一个链表,get的复杂度会变成O(n)。在Java8中为了优化该最坏情况下的性能,采用了平衡树来存放这些hash冲突的键值对,性能由此可以提升至O(logn)。代码块4 -- JDK8中HashMap中常量定义 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; static final int TREEIFY_THRESHOLD = 8; // 是否将list转换成tree的阈值 static final int UNTREEIFY_THRESHOLD = 6; // 在resize操作中,决定是否untreeify的阈值 static final int MIN_TREEIFY_CAPACITY = 64; // 决定是否转换成tree的最小容量 static final float DEFAULT_LOAD_FACTOR = 0.75f; // default的加载因子在Java 8 HashMap的put方法实现如代码块5所示,代码块5 --JDK8 HashMap.put方法 public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; //table为空的时候,n为table的长度 if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); // (n - 1) & hash 与Java7中indexFor方法的实现相同,若i位置上的值为空,则新建一个Node,table[i]指向该Node。 else { // 若i位置上的值不为空,判断当前位置上的Node p 是否与要插入的key的hash和key相同 Node<K,V> e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p;//相同则覆盖之 else if (p instanceof TreeNode) // 不同,且当前位置上的的node p已经是TreeNode的实例,则再该树上插入新的node。 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else { // 在i位置上的链表中找到p.next为null的位置,binCount计算出当前链表的长度,如果继续将冲突的节点插入到该链表中,会使链表的长度大于tree化的阈值,则将链表转换成tree。 for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }再看下resize方法,由于需要考虑hash冲突解决时采用的可能是list 也可能是balance tree的方式,因此resize方法相比JDK7中复杂了一些,代码块6 -- JDK8的resize方法 inal Node<K,V>[] resize() { Node<K,V>[] oldTab = table; int oldCap = (oldTab == null) ? 0 : oldTab.length; int oldThr = threshold; int newCap, newThr = 0; if (oldCap > 0) { if (oldCap >= MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE;//如果超过最大容量,无法再扩充table return oldTab; } else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY) newThr = oldThr << 1; // threshold门槛扩大至2倍 } else if (oldThr > 0) // initial capacity was placed in threshold newCap = oldThr; else { // zero initial threshold signifies using defaults newCap = DEFAULT_INITIAL_CAPACITY; newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); } if (newThr == 0) { float ft = (float)newCap * loadFactor; newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? (int)ft : Integer.MAX_VALUE); } threshold = newThr; @SuppressWarnings({"rawtypes","unchecked"}) Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];// 创建容量为newCap的newTab,并将oldTab中的Node迁移过来,这里需要考虑链表和tree两种情况。

java中hashset和hashmap有什么特点?

什么是HashSetHashSet实现了Set接口,它不允许集合中有重复的值,当我们提到HashSet时,第一件事情就是在将对象存储在HashSet之前,要先确保对象重写equals()和hashCode()方法,这样才能比较对象的值是否相等,以确保set中没有储存相等的对象。如果我们没有重写这两个方法,将会使用这个方法的默认实现。public boolean add(Object o)方法用来在Set中添加元素,当元素值重复时则会立即返回false,如果成功添加的话会返回true。什么是HashMapHashMap实现了Map接口,Map接口对键值对进行映射。Map中不允许重复的键。Map接口有两个基本的实现,HashMap和TreeMap。TreeMap保存了对象的排列次序,而HashMap则不能。HashMap允许键和值为null。HashMap是非synchronized的,但collection框架提供方法能保证HashMap synchronized,这样多个线程同时访问HashMap时,能保证只有一个线程更改Map。public Object put(Object Key,Object value)方法用来将元素添加到map中。你可以阅读这篇文章看看HashMap的工作原理,以及这篇文章看看HashMap和HashTable的区别。HashSet和HashMap的区别*HashMap* *HashSet* HashMap实现了Map接口 HashSet实现了Set接口 HashMap储存键值对 HashSet仅仅存储对象 使用put()方法将元素放入map中 使用add()方法将元素放入set中 HashMap中使用键对象来计算hashcode值 HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false HashMap比较快,因为是使用唯一的键来获取对象 HashSet较HashMap来说比较慢

hashtable和hashmap的区别是什么?

一、继承父类不同Hashtable继承自Dictionary类,而HashMap继承自AbstractMap类;但二者都实现了Map接口。二、线程的安全性1、HashTable是同步(方法中使用了Synchronize)的;而HashMap是未同步(方法中缺省Synchronize)的。2、Hashtable线程安全,因为它每个方法中都加入了Synchronize,在多线程并发的环境下,可以直接使用Hashtable,不需自己在加同步;HashMap线程不安全,因为HashMap底层是一个Entry数组,当发生hashmap冲突的时候,hashmap是采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。三、是否有contains方法1、HashTable有一个contains(Object value)方法,功能和containsValue方法(Object value)功能一样。2、HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey。四、可否允许有null值key、value都是对象,但是不能拥有重复key值,value值可以重复出现。1、Hashtable中,key和value都不允许出现null值。2、HashMap允许null值(key和value都可以),因为在HashMap中null可以作为健,而它对应的值可以有多个null。五、遍历方式内部实现不同1.HashTable使用Enumeration,HashMap使用Iterator。

Hashpmap的原理,HashMap怎样保证key的唯一性

并不能保证,但是可以通过判断,得到现在有无数据,若有,进入下一层。

如何实现线程安全的HashMap

HashTable不就可以吗。

java 为什么使用hashmap

http://blog.csdn.net/rickiyeat/article/details/52708794

Java中HashMap和TreeMap的区别深入理解

首先介绍一下什么是Map.在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value.这就是我们平时说的键值对。  HashMap通过hashcode对其内容进行快速查找,而 TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。  HashMap 非线程安全 TreeMap 非线程安全  线程安全  在Java里,线程安全一般体现在两个方面:  1、多个thread对同一个java实例的访问(read和modify)不会相互干扰,它主要体现在关键字synchronized.如ArrayList和Vector,HashMap和Hashtable  (后者每个方法前都有synchronized关键字)。如果你在interator一个List对象时,其它线程remove一个element,问题就出现了。  2、每个线程都有自己的字段,而不会在多个线程之间共享。它主要体现在java.lang.ThreadLocal类,而没有Java关键字支持,如像static、transient那样。  1.AbstractMap抽象类和SortedMap接口  AbstractMap抽象类:(HashMap继承AbstractMap)覆盖了equals()和hashCode()方法以确保两个相等映射返回相同的哈希码。如果两个映射大小相等、包含同样的键且每个键在这两个映射中对应的值都相同,则这两个映射相等。映射的哈希码是映射元素哈希码的总和,其中每个元素是Map.Entry接口的一个实现。因此,不论映射内部顺序如何,两个相等映射会报告相同的哈希码。  SortedMap接口:(TreeMap继承自SortedMap)它用来保持键的有序顺序。SortedMap接口为映像的视图(子集),包括两个端点提供了访问方法。除了排序是作用于映射的键以外,处理SortedMap和处理SortedSet一样。添加到SortedMap实现类的元素必须实现Comparable接口,否则您必须给它的构造函数提供一个Comparator接口的实现。TreeMap类是它的唯一一份实现。  2.两种常规Map实现  HashMap:基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals()[可以重写hashCode()和equals()],为了优化HashMap空间的使用,您可以调优初始容量和负载因子。  (1)HashMap(): 构建一个空的哈希映像  (2)HashMap(Map m): 构建一个哈希映像,并且添加映像m的所有映射  (3)HashMap(int initialCapacity): 构建一个拥有特定容量的空的哈希映像  (4)HashMap(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空的哈希映像  TreeMap:基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。  (1)TreeMap():构建一个空的映像树  (2)TreeMap(Map m): 构建一个映像树,并且添加映像m中所有元素  (3)TreeMap(Comparator c): 构建一个映像树,并且使用特定的比较器对关键字进行排序  (4)TreeMap(SortedMap s): 构建一个映像树,添加映像树s中所有映射,并且使用与有序映像s相同的比较器排序  3.两种常规Map性能  HashMap:适用于在Map中插入、删除和定位元素。  Treemap:适用于按自然顺序或自定义顺序遍历键(key)。  4.总结  HashMap通常比TreeMap快一点(树和哈希表的数据结构使然),建议多使用HashMap,在需要排序的Map时候才用TreeMap.  import java.util.HashMap;  import java.util.Hashtable;  import java.util.Iterator;  import java.util.Map;  import java.util.TreeMap;  public class HashMaps {  public static void main(String[] args) {  Map<String, String> map = new HashMap<String, String>();  map.put("a", "aaa");  map.put("b", "bbb");  map.put("c", "ccc");  map.put("d", "ddd");  Iterator<String> iterator = map.keySet()。iterator();  while (iterator.hasNext()) {  Object key = iterator.next();  System.out.println("map.get(key) is :" + map.get(key));  }  // 定义HashTable,用来测试  Hashtable<String, String> tab = new Hashtable<String, String>();  tab.put("a", "aaa");  tab.put("b", "bbb");  tab.put("c", "ccc");  tab.put("d", "ddd");  Iterator<String> iterator_1 = tab.keySet()。iterator();  while (iterator_1.hasNext()) {  Object key = iterator_1.next();  System.out.println("tab.get(key) is :" + tab.get(key));  }  TreeMap<String, String> tmp = new TreeMap<String, String>();  tmp.put("a", "aaa");  tmp.put("b", "bbb");  tmp.put("c", "ccc");  tmp.put("d", "cdc");  Iterator<String> iterator_2 = tmp.keySet()。iterator();  while (iterator_2.hasNext()) {  Object key = iterator_2.next();  System.out.println("tmp.get(key) is :" + tmp.get(key));  }  }  }  运行结果如下:  map.get(key) is :ddd  map.get(key) is :bbb  map.get(key) is :ccc  map.get(key) is :aaa  tab.get(key) is :bbb  tab.get(key) is :aaa  tab.get(key) is :ddd  tab.get(key) is :ccc  tmp.get(key) is :aaa  tmp.get(key) is :bbb  tmp.get(key) is :ccc  tmp.get(key) is :cdc  HashMap的结果是没有排序的,而TreeMap输出的结果是排好序的。  下面就要进入本文的主题了。先举个例子说明一下怎样使用HashMap:  import java.util.*;  public class Exp1 {  public static void main(String[] args){  HashMap h1=new HashMap();  Random r1=new Random();  for (int i=0;i<1000;i++){  Integer t=new Integer(r1.nextInt(20));  if (h1.containsKey(t))  ((Ctime)h1.get(t))。count++;  else  h1.put(t, new Ctime());  }  System.out.println(h1);  }  }  class Ctime{  int count=1;  public String toString(){  return Integer.toString(count);  }  } 在HashMap中通过get()来获取value,通过put()来插入value,ContainsKey()则用来检验对象是否已经存在。可以看出,和ArrayList的操作相比,HashMap除了通过key索引其内容之外,别的方面差异并不大。  前面介绍了,HashMap是基于HashCode的,在所有对象的超类Object中有一个HashCode()方法,但是它和equals方法一样,并不能适用于所有的情况,这样我们就需要重写自己的HashCode()方法。下面就举这样一个例子:  import java.util.*;  public class Exp2 {  public static void main(String[] args){  HashMap h2=new HashMap();  for (int i=0;i<10;i++)  h2.put(new Element(i), new Figureout());  System.out.println("h2:");  System.out.println("Get the result for Element:");  Element test=new Element(5);  if (h2.containsKey(test))  System.out.println((Figureout)h2.get(test));  else  System.out.println("Not found");  }  }  class Element{  int number;  public Element(int n){  number=n;  }  }  class Figureout{  Random r=new Random();  boolean possible=r.nextDouble()>0.5;  public String toString(){  if (possible)  return "OK!";  else  return "Impossible!";  }  }  在这个例子中,Element用来索引对象Figureout,也即Element为key,Figureout为value.在Figureout中随机生成一个浮点数,如果它比0.5大,打印"OK!",否则打印"Impossible!".之后查看Element(3)对应的Figureout结果如何。  结果却发现,无论你运行多少次,得到的结果都是"Not found".也就是说索引Element(3)并不在HashMap中。这怎么可能呢?  原因得慢慢来说:Element的HashCode方法继承自Object,而Object中的HashCode方法返回的HashCode对应于当前的地址,也就是说对于不同的对象,即使它们的内容完全相同,用HashCode()返回的值也会不同。这样实际上违背了我们的意图。因为我们在使用 HashMap时,希望利用相同内容的对象索引得到相同的目标对象,这就需要HashCode()在此时能够返回相同的值。在上面的例子中,我们期望 new Element(i) (i=5)与 Elementtest=newElement(5)是相同的,而实际上这是两个不同的对象,尽管它们的内容相同,但它们在内存中的地址不同。因此很自然的,上面的程序得不到我们设想的结果。下面对Element类更改如下:  class Element{  int number;  public Element(int n){  number=n;  }  public int hashCode(){  return number;  }  public boolean equals(Object o){  return (o instanceof Element) && (number==((Element)o)。number);  }  }  在这里Element覆盖了Object中的hashCode()和equals()方法。覆盖hashCode()使其以number的值作为 hashcode返回,这样对于相同内容的对象来说它们的hashcode也就相同了。而覆盖equals()是为了在HashMap判断两个key是否相等时使结果有意义(有关重写equals()的内容可以参考我的另一篇文章《重新编写Object类中的方法》)。修改后的程序运行结果如下:  h2:  Get the result for Element:  Impossible!  请记住:如果你想有效的使用HashMap,你就必须重写在其的HashCode()。  还有两条重写HashCode()的原则:  [list=1]  不必对每个不同的对象都产生一个唯一的hashcode,只要你的HashCode方法使get()能够得到put()放进去的内容就可以了。即"不为一原则".  生成hashcode的算法尽量使hashcode的值分散一些,不要很多hashcode都集中在一个范围内,这样有利于提高HashMap的性能。即"分散原则".至于第二条原则的具体原因,有兴趣者可以参考Bruce Eckel的《Thinking in Java》,在那里有对HashMap内部实现原理的介绍,这里就不赘述了。  掌握了这两条原则,你就能够用好HashMap编写自己的程序了。不知道大家注意没有,java.lang.Object中提供的三个方法:clone(),equals()和hashCode()虽然很典型,但在很多情况下都不能够适用,它们只是简单的由对象的地址得出结果。这就需要我们在自己的程序中重写它们,其实java类库中也重写了千千万万个这样的方法。利用面向对象的多态性--覆盖,Java的设计者很优雅的构建了Java的结构,也更加体现了Java是一门纯OOP语言的特性。
 1 2 3 4 5 6  下一页  尾页