当前位置: 首页 > wzjs >正文

泉州住房和城乡建设网站湛江seo

泉州住房和城乡建设网站,湛江seo,购物节优惠卷网站怎么做,华东民航机场建设公司网站因为我们java的util包下的常用集合类java.util.ArrayList、java.util.HashMap都是非线程安全的,虽然Vector和Hashtable是线程安全的,但是因为大部分方法都是通过synchronized关键字修饰,性能太低。 于是,从jdk1.5开始,…

因为我们java的util包下的常用集合类java.util.ArrayList、java.util.HashMap都是非线程安全的,虽然Vector和Hashtable是线程安全的,但是因为大部分方法都是通过synchronized关键字修饰,性能太低。

于是,从jdk1.5开始,java开发者提供了性能更高的线程安全类ConcurrentHashMap和CopyOnWriteArrayList。

目录

CopyOnWriteArrayList

静态方法

indexOf

 lastIndexOf

实例方法

contains

indexOf

lastIndexOf

toArray()

get

set

add

remove

removeRange

addIfAbsent

containsAll

addAllAbsent

clear

addAll

forEach

removeIf

replaceAll

sort


CopyOnWriteArrayList

CopyOnWriteArrayList是jdk1.5推出的一个能保证线程安全的List接口实现类,底层也基于动态数组实现的。其设计思想是写时复制(Copy On Write),在修改操作中,会复制一份原来的数组,在新的数组上修改,不会直接修改原来的数组,所以对读操作没有影响。

CopyOnWriteArrayList内部使用了ReentrantLock保证修改操作线程安全。

public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable,  java.io.Serializable {private static final long serialVersionUID = 8673264195747942595L;final transient ReentrantLock lock = new ReentrantLock();// volatile修饰,保证setArray(arr)方法执行后,array的修改对其他线程立即可见 private transient volatile Object[] array;final Object[] getArray() {return array;}final void setArray(Object[] a) {array = a;}public CopyOnWriteArrayList() {// 无参构造方法,初始化一个空数组setArray(new Object[0]);}public CopyOnWriteArrayList(Collection<? extends E> c) {Object[] elements;// 如果参数是CopyOnWriteArrayList类型的,直接把当前CopyOnWriteArrayList对象的array设置成c.getArray()if (c.getClass() == CopyOnWriteArrayList.class) {elements = ((CopyOnWriteArrayList<?>)c).getArray();} else {// 不同类型,调用list.toArray()把集合转成数组elements = c.toArray();if (elements.getClass() != Object[].class) {elements = Arrays.copyOf(elements, elements.length, Object[].class);}}setArray(elements);}public CopyOnWriteArrayList(E[] toCopyIn) {setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));}public int size() {return getArray().length;}public boolean isEmpty() {return size() == 0;}private static boolean eq(Object o1, Object o2) {return (o1 == null) ? o2 == null : o1.equals(o2);}}

上面是一些基础的方法,接下来介绍CopyOnWriteArrayList的其他方法:

静态方法

如果你第一次看CopyOnWriteArrayList的源码,你可能会和我一样觉得这两个方法不应该出现在这里,这就是数组相关的方法,接着往下看,你会发现,这两个方法就是提供后面的方法内部调用的。

indexOf

静态方法,获取指定元素在数组中下标从index到fence中有没有出现过,如果出现过,返回第一次出现的位置,如果找不到就返回-1。

    private static int indexOf(Object o, Object[] elements, int index, int fence) {if (o == null) {for (int i = index; i < fence; i++)if (elements[i] == null)return i;} else {for (int i = index; i < fence; i++)if (o.equals(elements[i]))return i;}return -1;}

 lastIndexOf

静态方法,获取指定元素在数组中最后一次出现的位置,如果找不到就返回-1。

从数组的末尾元素往前遍历,找到的第一个匹配的元素的下标就是所需的结果。

    private static int lastIndexOf(Object o, Object[] elements, int index) {if (o == null) {for (int i = index; i >= 0; i--)if (elements[i] == null)return i;} else {for (int i = index; i >= 0; i--)if (o.equals(elements[i]))return i;}return -1;}

实例方法

contains

判断当前list中是否包含指定的元素,通过调用静态方法indexOf(),根据是否返回-1来判断,返回-1则表示数组中没有匹配到该元素,所以就是返回false,否则返回true。

    public boolean contains(Object o) {Object[] elements = getArray();return indexOf(o, elements, 0, elements.length) >= 0;}

indexOf

获取指定元素在当前list中第一次出现的位置

    public int indexOf(Object o) {Object[] elements = getArray();return indexOf(o, elements, 0, elements.length);}

获取指定元素在当前list中从下标index开始,第一次出现的位置

    public int indexOf(E e, int index) {Object[] elements = getArray();return indexOf(e, elements, index, elements.length);}

lastIndexOf

获取指定元素在当前list中最后一次出现的位置,如果找不到就返回-1。

    public int lastIndexOf(Object o) {Object[] elements = getArray();return lastIndexOf(o, elements, elements.length - 1);}

 获取指定元素在当前list中最后一次出现的位置,从数组下标index位置开始匹配

    public int lastIndexOf(E e, int index) {Object[] elements = getArray();return lastIndexOf(e, elements, index);}

toArray()

返回当前list内部的数组的副本

    public Object[] toArray() {Object[] elements = getArray();return Arrays.copyOf(elements, elements.length);}

返回当前list内部的数组的副本,并将其转换为指定类型

    public <T> T[] toArray(T a[]) {Object[] elements = getArray();int len = elements.length;if (a.length < len)return (T[]) Arrays.copyOf(elements, len, a.getClass());else {System.arraycopy(elements, 0, a, 0, len);// 这句代码似乎有点多余if (a.length > len)a[len] = null;return a;}}

get

私有的方法,获取数组指定下标的元素,并将其转换为和list元素类型相同的数据类型。

    private E get(Object[] a, int index) {return (E) a[index];}

获取数组指定下标的元素,并将其转换为和list元素类型相同的数据类型。

    public E get(int index) {return get(getArray(), index);}

set

修改list指定位置的元素,通过ReentrantLock保证写操作的线程安全

    public E set(int index, E element) {final ReentrantLock lock = this.lock;lock.lock();try {// 得到当前list内部的数组Object[] elements = getArray();// 获取指定下标的值E oldValue = get(elements, index);// 当旧值和新值不相等时,修改副本if (oldValue != element) {int len = elements.length;// 得到数组的副本Object[] newElements = Arrays.copyOf(elements, len);newElements[index] = element;setArray(newElements);} else {setArray(elements);}return oldValue;} finally {lock.unlock();}}

add

往list里添加元素,通过ReentrantLock保证写操作的线程安全

和set方法一样,对原数组的副本进行操作,先扩容,然后设置数组最后一个下标的值,修改完成后,把副本指向原来的数组。

    public boolean add(E e) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;Object[] newElements = Arrays.copyOf(elements, len + 1);newElements[len] = e;setArray(newElements);return true;} finally {lock.unlock();}}

往list指定下标处添加元素

    public void add(int index, E element) {final ReentrantLock lock = this.lock;lock.lock();try {// 得到原数组Object[] elements = getArray();int len = elements.length;if (index > len || index < 0)throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + len);Object[] newElements;int numMoved = len - index;// 插入位置和数组的长度相等,则等同于add(E element )if (numMoved == 0)newElements = Arrays.copyOf(elements, len + 1);else {// 把原来的数组分两次复制到新数组中newElements = new Object[len + 1];System.arraycopy(elements, 0, newElements, 0, index);System.arraycopy(elements, index, newElements, index + 1, numMoved);}// 设置数组指定位置的元素newElements[index] = element;// 把新数组指向原数组setArray(newElements);} finally {lock.unlock();}}

remove

获取并删除指定位置的元素

    public E remove(int index) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;E oldValue = get(elements, index);int numMoved = len - index - 1;// 如果指定下标+1=原数组长度,则是删除最后一个元素,只需要进行数组缩容if (numMoved == 0)setArray(Arrays.copyOf(elements, len - 1));else {// 创建一个原数组长度-1的数组,把除了index下标的元素复制到新数组Object[] newElements = new Object[len - 1];System.arraycopy(elements, 0, newElements, 0, index);System.arraycopy(elements, index + 1, newElements, index, numMoved);// 把新数组指向原数组setArray(newElements);}// 返回删除的元素return oldValue;} finally {lock.unlock();}}

从list中删除指定元素

    public boolean remove(Object o) {Object[] snapshot = getArray();int index = indexOf(o, snapshot, 0, snapshot.length);return (index < 0) ? false : remove(o, snapshot, index);}

 私有的方法,删除list中指定的元素

    private boolean remove(Object o, Object[] snapshot, int index) {final ReentrantLock lock = this.lock;lock.lock();try {// 得到原数组Object[] current = getArray();int len = current.length;// 如果指定的数组和原数组不相等if (snapshot != current) findIndex: {// 得到index和原数组长度之间的最小值int prefix = Math.min(index, len);for (int i = 0; i < prefix; i++) {// current[i] != snapshot[i]说明array被修改过// array被修改过,并且修改之后的元素和指定的元素相等if (current[i] != snapshot[i] && eq(o, current[i])) {index = i;break findIndex;}}// 下标越界if (index >= len)return false;// 再次检查原数组是否被修改过if (current[index] == o)break findIndex;// 找不到指定元素,直接返回falseindex = indexOf(o, current, index, len);if (index < 0)return false;}// 分段复制到新数组,最后替换原来的arrayObject[] newElements = new Object[len - 1];System.arraycopy(current, 0, newElements, 0, index);System.arraycopy(current, index + 1, newElements, index, len - index - 1);setArray(newElements);return true;} finally {lock.unlock();}}

removeRange

从list中删除指定下标范围 [fromIndex, toIndex] 的元素

    void removeRange(int fromIndex, int toIndex) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;// 检查参数大小if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)throw new IndexOutOfBoundsException();int newlen = len - (toIndex - fromIndex);int numMoved = len - toIndex;// 删除的是数组后半段if (numMoved == 0)setArray(Arrays.copyOf(elements, newlen));else {// 删除数组中间的部分,还是分两步复制到新数组中,最后修改array的引用Object[] newElements = new Object[newlen];System.arraycopy(elements, 0, newElements, 0, fromIndex);System.arraycopy(elements, toIndex, newElements, fromIndex, numMoved);setArray(newElements);}} finally {lock.unlock();}}

addIfAbsent

如果指定元素不存在则添加

    public boolean addIfAbsent(E e) {Object[] snapshot = getArray();return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false : addIfAbsent(e, snapshot);}
    private boolean addIfAbsent(E e, Object[] snapshot) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] current = getArray();int len = current.length;if (snapshot != current) {int common = Math.min(snapshot.length, len);for (int i = 0; i < common; i++) {// 原数组array被修改过,并且修改之后的数组中存在指定元素if (current[i] != snapshot[i] && eq(e, current[i])) {return false;}}// 元素已经存在if (indexOf(e, current, common, len) >= 0) {return false;}}// 数组扩容,把当前元素设置到数组末尾Object[] newElements = Arrays.copyOf(current, len + 1);newElements[len] = e;setArray(newElements);return true;} finally {lock.unlock();}}

containsAll

判断当前list是否包含集合c内所有元素

    public boolean containsAll(Collection<?> c) {Object[] elements = getArray();int len = elements.length;for (Object e : c) {if (indexOf(e, elements, 0, len) < 0) {return false;}   }return true;}

    public boolean removeAll(Collection<?> c) {if (c == null) throw new NullPointerException();final ReentrantLock lock = this.lock;lock.lock();try {// 得到原数组及长度Object[] elements = getArray();int len = elements.length;if (len != 0) {// 创建一个变量保存删除元素后数组的长度int newlen = 0;// 创建一个临时数组,指定初始长度和原元素的长度相同Object[] temp = new Object[len];// 遍历原数组,for (int i = 0; i < len; ++i) {Object element = elements[i];// 如果元素没有包含在指定集合c中,把元素添加到临时数组,同时结果数组长度+1if (!c.contains(element))temp[newlen++] = element;}// 如果有匹配的元素,对临时数组缩容if (newlen != len) {setArray(Arrays.copyOf(temp, newlen));return true;}}return false;} finally {lock.unlock();}}

addAllAbsent

往list中添加原数组和指定集合元素的差集,也就是集合c里的array里没有的元素。

    public int addAllAbsent(Collection<? extends E> c) {// 指定集合转为数组Object[] cs = c.toArray();if (cs.length == 0)return 0;final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;// 保存最后添加成功的元素个数int added = 0;// 遍历指定的集合cfor (int i = 0; i < cs.length; ++i) {Object e = cs[i];// 原数组中没有的元素放到cs中// indexOf(e, cs, 0, added) < 0限制了不会往cs中添加重复的元素if (indexOf(e, elements, 0, len) < 0 && indexOf(e, cs, 0, added) < 0)cs[added ++] = e;}/*最后,如果有符合条件的元素,则从cs中复制元素因为上面的操作中,把符合条件的元素放在了数组cs的0~added位置*/if (added > 0) {Object[] newElements = Arrays.copyOf(elements, len + added);System.arraycopy(cs, 0, newElements, len, added);// 替换旧数组setArray(newElements);}return added;} finally {lock.unlock();}}

clear

清空集合,这个功能没什么好说的,直接设置array为空数组

    public void clear() {final ReentrantLock lock = this.lock;lock.lock();try {setArray(new Object[0]);} finally {lock.unlock();}}

addAll

把集合c中的元素添加到当前list中

    public boolean addAll(Collection<? extends E> c) {// 把集合c转为数组Object[] cs = (c.getClass() == CopyOnWriteArrayList.class) ?((CopyOnWriteArrayList<?>)c).getArray() : c.toArray();if (cs.length == 0)return false;final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;// 原数组为空数组,且指定集合c的元素类型为Object,直接把集合c转换得到的的数组指向arrayif (len == 0 && cs.getClass() == Object[].class) {setArray(cs);} else {// 先对原数组扩容,扩容后的长度=原数组长度 + 集合c的元素个数Object[] newElements = Arrays.copyOf(elements, len + cs.length);// 从集合c的数组中复制元素System.arraycopy(cs, 0, newElements, len, cs.length);// 修改array的引用setArray(newElements);}return true;} finally {lock.unlock();}}

把集合c中的元素添加到当前list中,新元素会替换原来的list中数组在[index, index + c.size()]的元素

    public boolean addAll(int index, Collection<? extends E> c) {Object[] cs = c.toArray();final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;if (index > len || index < 0)throw new IndexOutOfBoundsException("Index: " + index + ", Size: "+len);if (cs.length == 0)return false;int numMoved = len - index;Object[] newElements;// index和原数组长度相等,则直接对数组进行扩容if (numMoved == 0)newElements = Arrays.copyOf(elements, len + cs.length);else {// 分段复制,把原数组首尾的元素复制到数组newElements中newElements = new Object[len + cs.length];System.arraycopy(elements, 0, newElements, 0, index);System.arraycopy(elements, index, newElements, index + cs.length, numMoved);}// 把指定集合的元素复制到newElements中间[index, index + cs.length]System.arraycopy(cs, 0, newElements, index, cs.length);setArray(newElements);return true;} finally {lock.unlock();}}

forEach

遍历集合,这个方法大家再熟悉不过了吧,Java集合的4种遍历方式之一(for foreach Iterater forEach方法)。

    public void forEach(Consumer<? super E> action) {if (action == null) throw new NullPointerException();Object[] elements = getArray();int len = elements.length;for (int i = 0; i < len; ++i) {E e = (E) elements[i];action.accept(e);}}

removeIf

条件删除集合中的元素,使用该方法可以防止快速失败,也是集合常用的方法,就不介绍了。

    public boolean removeIf(Predicate<? super E> filter) {if (filter == null) throw new NullPointerException();final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;if (len != 0) {int newlen = 0;Object[] temp = new Object[len];// 重点:把不符合条件的元素保存在临时数组temp中for (int i = 0; i < len; ++i) {E e = (E) elements[i];if (!filter.test(e))temp[newlen++] = e;}// 新长度和原数组长度不相等,也就是删除了元素才进行数组缩容if (newlen != len) {setArray(Arrays.copyOf(temp, newlen));return true;}}return false;} finally {lock.unlock();}}

replaceAll

替换全部元素,其实就是对集合进行批量操作

    public void replaceAll(UnaryOperator<E> operator) {if (operator == null) throw new NullPointerException();final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;Object[] newElements = Arrays.copyOf(elements, len);for (int i = 0; i < len; ++i) {E e = (E) elements[i];newElements[i] = operator.apply(e);}setArray(newElements);} finally {lock.unlock();}}

UnaryOperator是个函数式接口,继承了Function接口,表示一次简单的操作,在apply()方法中,可以对传入的参数做任何处理。

package java.util.function;@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {static <T> UnaryOperator<T> identity() {return t -> t;}
}

可以看到,UnaryOperator也没有实现Function的apply()方法,所以实例化的时候需要实现UnaryOperator继承自Function接口的apply()方法。

package java.util.function;import java.util.Objects;@FunctionalInterface
public interface Function<T, R> {R apply(T t);default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {Objects.requireNonNull(before);return (V v) -> apply(before.apply(v));}default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {Objects.requireNonNull(after);return (T t) -> after.apply(apply(t));}static <T> Function<T, T> identity() {return t -> t;}
}

这个接口可以比较抽象,通过一个案例用一下就知道了。下面的代码在集合所有元素后面拼接了字符串"~"。

package juc;import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.UnaryOperator;/*** @author heyunlin* @version 1.0*/
public class CopyOnWriteArrayListExample {public static void main(String[] args) {CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();list.add("abc");list.add("123");System.out.println(list);list.replaceAll(new UnaryOperator<String>() {@Overridepublic String apply(String s) {return s.concat("~");}});System.out.println(list);}}

sort

在集合的工具类Collections里就有一个排序的静态方法sort(),通过传入的比较器对象自定义排序规则,返回负数代表降序,返回正数代表升序

    public void sort(Comparator<? super E> c) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();Object[] newElements = Arrays.copyOf(elements, elements.length);E[] es = (E[]) newElements;Arrays.sort(es, c);setArray(newElements);} finally {lock.unlock();}}

好了,关于CopyOnWriteArrayList方法的详细介绍就到这里了,看完不要忘了点赞+收藏哦~

http://www.dtcms.com/wzjs/53683.html

相关文章:

  • 试用网站源码小学培训机构
  • 黄山区建设学会网站廊坊今日头条新闻
  • 阿里云的网站模版好吗台州seo网站排名优化
  • 网站安全认证去哪做网站推广app软件
  • wordpress 并发量优化seo搜索
  • 如何提升网站用户体验宁波网站制作设计
  • 温州市建设厅网站首页站长工具ip查询
  • 住房和城乡建设部2019年安全生产工作要点衡阳seo优化推荐
  • jsp做物流网站南昌seo公司
  • 论坛网站建设价格俄罗斯搜索引擎浏览器
  • 想做一个能上传视频的网站怎么做发帖平台
  • 做网站页面的框架优化设计答案
  • 毕业答辩ppt网站开发长尾关键词是什么
  • 深圳做网站推广优化山东进一步优化
  • seo网站服务公司百度推广一个月费用
  • 自己做的网站视频播放不了电脑培训学校网站
  • 网上有做衣服的网站有哪些seo优化推广业务员招聘
  • 做网站时的注册权起到什么作用网站在线生成app
  • 梦想小镇旅游官方网站建设seo综合查询站长工具关键词
  • 做网站的公司面试网站建设解决方案
  • 长沙公司做网站seo分析报告
  • 深圳做棋牌网站建设哪家技术好搜索引擎优化的内容
  • 网站建设实现后台数据导出excel武汉网站营销seo方案
  • vs2013做网站百度经验官网首页
  • 参考文献 教学网站建设今日新闻简讯30条
  • 唐山专业网站建设广州seo外包公司
  • 初学者学做网站怎么学seo网络推广什么意思
  • 农业推广学搜索引擎优化的简称
  • 网站系统建设凡科建站app
  • 网站表格怎么做徐州seo推广优化