人家叫ADT adt是啥呢
表的简单数组实现
自我理解
某技师(数组)手法很好,以至于很多lsp点,大保健按先后顺序排队发号,奇怪的是这位技师每天只接30个(楼下有小牌写着今天接待30位),多了不接,所以号码牌(索引)就从0 发到29,
然后她有个习惯,每次发完号她还要自己确定一遍(遍历:查找的很快啊),从头到尾这么一看,哎,有个老灯,这个老灯在第一位(老灯有钱,跟别人加价买的号)(索引为0,因为索引从0开始),她不愿意接待
老灯,就跟看场的小老弟(机器人)说你去把他的号要过来(删除元素),这时候后面的号就得往前移动,你想啊,第一个人被赶走了,号被拿走了,自然第二个人就成了第一个,但是呢,小老弟得挨个把他们的号更新
架不住啊这老灯有钱,每次都点这位,而且每次都想加价买第一个号(index = 0),开始还让老灯在最后一个排着,一来二去小老弟也烦了,要挟技师奥里给一下子,要不就告诉老板她偷摸加活儿(你懂的),你想想头牌岂是你一小老弟能威胁的,头牌间接的告诉了boss(GC),boss
有一天趁小老弟休息,就给他整碎了,boss有钱,然后呢,过了一段时间,头牌说想改一下接待人数,号码也要换新的,牌子得改数,boss就又整(new)了一个小老弟,让他负责这些事情,老灯又得到了消息,
于是这天又来了,发现小牌写着接待人数变成了20人,他就上去了,惯例,加钱想买0号。
新来的小老弟叫列表(LinkedList),这小伙牛,取消了之前排队政策,而且呢,他排队特别,排号的人随便坐(LinkedList地址值不连续),告诉了每个人的前面的人是谁(单向链表当前节点指向后继节点的地址值),后面是谁,这样不拥挤,可这下老灯懵逼了,他说谁是0号,我加钱买0号,好家伙,黑了股东的倒是听见了有人说是0号,
老灯得找啊,这下给老灯找的,他就听声辩位,不小心按大哥的二弟上了(表中其他非0号元素),好嘛,你想想大哥这二弟好惹么,不,大哥是好惹的么,伸手就给老灯一拳,老灯说你看你这年轻人,不讲武德,咋还偷袭我这老灯呢,
咱们别搞窝里斗,就继续找0号去了,这次有大哥的电炮加持,费了老大劲可算找到了0号,加了钱换过来了,这时候原来的0号就是就是老灯,然后列表只需要告诉老灯(now.next())他后面是谁就完事了,而且规定了不能让后面的人知道前面的人是谁,
这样能防老灯,果然,下次老灯来了又问谁是0号,没人搭理他,他只能排到第20位了等着了,
总结
可以这样说:当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能;当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。
ArrayList 是线性表(数组)
get() 直接读取第几个下标,复杂度 O(1)
add(E) 添加元素,直接在后面添加,复杂度O(1)
add(index, E) 添加元素,在第几个元素后面插入,后面的元素需要向后移动,复杂度O(n)
remove()删除元素,后面的元素需要逐个移动,复杂度O(n)
LinkedList 是双向链表的操作
get() 获取第几个元素,依次遍历,复杂度O(n)
add(E) 添加到末尾,复杂度O(1)
add(index, E) 添加第几个元素后,需要先查找到第几个元素,直接修改指针指向操作,复杂度O(n)
remove()删除元素,直接指针指向操作,复杂度O(1)
public static void main(String[] args) { HashSet<Integer> set = new HashSet(); for (int i = 0; i < 1000; i++) { set.add(i); } int sum = 0; Iterator iterator = set.iterator(); // 迭代器删除元素 while (iterator.hasNext()) { if ((int) iterator.next() % 2 == 0) { // 切记 如果使用迭代器,就必须用迭代器的remove 删除元素 iterator.remove(); // 如果使用Collection本身的remove 会抛出java.util.ConcurrentModificationException set.remove(iterator.next()); ++sum; } } System.out.println("sum:" + sum); }
比如老灯加价换了原来索引位置为0的元素 那么就可以是 list.set(0, '老灯') // 这句话的意思是将原来索引为0的元素换为老灯