001package io.ebean.common; 002 003import java.io.Serializable; 004import java.util.AbstractList; 005import java.util.ArrayList; 006import java.util.Collection; 007import java.util.Comparator; 008import java.util.List; 009import java.util.function.Predicate; 010import java.util.function.UnaryOperator; 011 012/** 013 * List that copies itself on first write access. Needed to keep memory footprint low and the ability 014 * to modify lists from cache. 015 * 016 * @author Roland Praml, FOCONIS AG 017 */ 018public final class CopyOnFirstWriteList<E> extends AbstractList<E> implements List<E>, Serializable { 019 020 private static final long serialVersionUID = 1L; 021 022 /** 023 * The underlying List implementation. 024 */ 025 private List<E> list; 026 027 028 public CopyOnFirstWriteList(List<E> list) { 029 super(); 030 this.list = list; 031 } 032 033 private volatile boolean copied = false; 034 035 @Override 036 public int size() { 037 return list.size(); 038 } 039 040 @Override 041 public boolean isEmpty() { 042 return list.isEmpty(); 043 } 044 045 @Override 046 public boolean contains(Object o) { 047 return list.contains(o); 048 } 049 050 @Override 051 public Object[] toArray() { 052 return list.toArray(); 053 } 054 055 @Override 056 public <T> T[] toArray(T[] a) { 057 return list.toArray(a); 058 } 059 060 @Override 061 public boolean add(E e) { 062 checkCopyOnWrite(); 063 return list.add(e); 064 } 065 066 @Override 067 public boolean remove(Object o) { 068 checkCopyOnWrite(); 069 return list.remove(o); 070 } 071 072 @Override 073 public boolean containsAll(Collection<?> c) { 074 return list.containsAll(c); 075 } 076 077 @Override 078 public boolean addAll(Collection<? extends E> c) { 079 checkCopyOnWrite(); 080 return list.addAll(c); 081 } 082 083 @Override 084 public boolean addAll(int index, Collection<? extends E> c) { 085 checkCopyOnWrite(); 086 return list.addAll(index, c); 087 } 088 089 @Override 090 public boolean removeAll(Collection<?> c) { 091 checkCopyOnWrite(); 092 return list.removeAll(c); 093 } 094 095 @Override 096 public boolean retainAll(Collection<?> c) { 097 checkCopyOnWrite(); 098 return list.retainAll(c); 099 } 100 101 @Override 102 public void replaceAll(UnaryOperator<E> operator) { 103 checkCopyOnWrite(); 104 list.replaceAll(operator); 105 } 106 107 @Override 108 public boolean removeIf(Predicate<? super E> filter) { 109 checkCopyOnWrite(); 110 return list.removeIf(filter); 111 } 112 113 @Override 114 public void sort(Comparator<? super E> c) { 115 checkCopyOnWrite(); 116 list.sort(c); 117 } 118 119 @Override 120 public void clear() { 121 if (!copied) { 122 list = new ArrayList<>(); 123 copied = true; 124 } 125 } 126 127 @Override 128 public boolean equals(Object o) { 129 return list.equals(o); 130 } 131 132 @Override 133 public int hashCode() { 134 return list.hashCode(); 135 } 136 137 @Override 138 public E get(int index) { 139 return list.get(index); 140 } 141 142 @Override 143 public E set(int index, E element) { 144 checkCopyOnWrite(); 145 return list.set(index, element); 146 } 147 148 @Override 149 public void add(int index, E element) { 150 checkCopyOnWrite(); 151 list.add(index, element); 152 } 153 154 @Override 155 public E remove(int index) { 156 checkCopyOnWrite(); 157 return list.remove(index); 158 } 159 160 @Override 161 public int indexOf(Object o) { 162 return list.indexOf(o); 163 } 164 165 @Override 166 public int lastIndexOf(Object o) { 167 return list.lastIndexOf(o); 168 } 169 170 private void checkCopyOnWrite() { 171 if (!copied) { 172 synchronized (this) { 173 if (!copied) { 174 list = new ArrayList<>(list); 175 copied = true; 176 } 177 } 178 } 179 } 180}