· 8 years ago · Mar 04, 2018, 12:46 PM
1package lab6;
2
3import lab5.devices.Device;
4
5import java.util.*;
6import java.util.function.Consumer;
7import java.util.function.Predicate;
8import java.util.function.UnaryOperator;
9
10/**
11 * Created by svidr on 2/21/2018.
12 */
13public class Devices extends AbstractList<Device> implements List<Device> {
14 private static final long serialVersionUID = 8683452581122892189L;
15
16 /**
17 * Default initial capacity.
18 */
19 private static final int DEFAULT_CAPACITY = 10; // LOOOOOOOOOOOOOOOOOOOOOOOOOOOOL
20
21 /**
22 * Shared empty array instance used for empty instances.
23 */
24 private static final Device[] EMPTY_ELEMENTDATA = {};
25
26 /**
27 * Shared empty array instance used for default sized empty instances. We
28 * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
29 * first element is added.
30 */
31 private static final Device[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
32
33 /**
34 * The array buffer into which the elements of the Devices are stored.
35 * The capacity of the Devices is the length of this array buffer. Any
36 * empty Devices with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
37 * will be expanded to DEFAULT_CAPACITY when the first element is added.
38 */
39 transient Device[] elementData; // non-private to simplify nested class access
40
41 /**
42 * The size of the Devices (the number of elements it contains).
43 *
44 * @serial
45 */
46 private int size;
47
48 /**
49 * Constructs an empty list with the specified initial capacity.
50 *
51 * @param initialCapacity the initial capacity of the list
52 * @throws IllegalArgumentException if the specified initial capacity
53 * is negative
54 */
55 public Devices(int initialCapacity) {
56 if (initialCapacity > 0) {
57 this.elementData = new Device[initialCapacity];
58 } else if (initialCapacity == 0) {
59 this.elementData = EMPTY_ELEMENTDATA;
60 } else {
61 throw new IllegalArgumentException("Illegal Capacity: " +
62 initialCapacity);
63 }
64 }
65
66 /**
67 * Constructs an empty list with an initial capacity of ten.
68 */
69 public Devices() {
70 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
71 }
72
73 /**
74 * Constructs a list containing the elements of the specified
75 * collection, in the order they are returned by the collection's
76 * iterator.
77 *
78 * @param c the collection whose elements are to be placed into this list
79 * @throws NullPointerException if the specified collection is null
80 */
81 public Devices(Devices c) {
82 elementData = c.elementData;
83 if ((size = elementData.length) != 0) {
84 // c.toArray might (incorrectly) not return Object[] (see 6260652)
85 if (elementData.getClass() != Device[].class)
86 elementData = Arrays.copyOf(elementData, size, Device[].class);
87 } else {
88 // replace with empty array.
89 this.elementData = EMPTY_ELEMENTDATA;
90 }
91 }
92
93 /**
94 * Trims the capacity of this <tt>Devices</tt> instance to be the
95 * list's current size. An application can use this operation to minimize
96 * the storage of an <tt>Devices</tt> instance.
97 */
98 public void trimToSize() {
99 modCount++;
100 if (size < elementData.length) {
101 elementData = (size == 0)
102 ? EMPTY_ELEMENTDATA
103 : Arrays.copyOf(elementData, size);
104 }
105 }
106
107 /**
108 * Increases the capacity of this <tt>Devices</tt> instance, if
109 * necessary, to ensure that it can hold at least the number of elements
110 * specified by the minimum capacity argument.
111 *
112 * @param minCapacity the desired minimum capacity
113 */
114 public void ensureCapacity(int minCapacity) {
115 int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
116 // any size if not default element table
117 ? 0
118 // larger than default for default empty table. It's already
119 // supposed to be at default size.
120 : DEFAULT_CAPACITY;
121
122 if (minCapacity > minExpand) {
123 ensureExplicitCapacity(minCapacity);
124 }
125 }
126
127 private void ensureCapacityInternal(int minCapacity) {
128 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
129 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
130 }
131
132 ensureExplicitCapacity(minCapacity);
133 }
134
135 private void ensureExplicitCapacity(int minCapacity) {
136 modCount++;
137
138 // overflow-conscious code
139 if (minCapacity - elementData.length > 0)
140 grow(minCapacity);
141 }
142
143 /**
144 * The maximum size of array to allocate.
145 * Some VMs reserve some header words in an array.
146 * Attempts to allocate larger arrays may result in
147 * OutOfMemoryError: Requested array size exceeds VM limit
148 */
149 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
150
151 /**
152 * Increases the capacity to ensure that it can hold at least the
153 * number of elements specified by the minimum capacity argument.
154 *
155 * @param minCapacity the desired minimum capacity
156 */
157 private void grow(int minCapacity) {
158 // overflow-conscious code //loooool
159 int oldCapacity = elementData.length;
160 int newCapacity = oldCapacity + (oldCapacity >> 1); // CYKA!!!!!!!!!!!!!!!!!! +50%
161 if (newCapacity - minCapacity < 0)
162 newCapacity = minCapacity;
163 if (newCapacity - MAX_ARRAY_SIZE > 0)
164 newCapacity = hugeCapacity(minCapacity);
165 // minCapacity is usually close to size, so this is a win:
166 elementData = Arrays.copyOf(elementData, newCapacity);
167 }
168
169 private static int hugeCapacity(int minCapacity) {
170 if (minCapacity < 0) // overflow
171 throw new OutOfMemoryError();
172 return (minCapacity > MAX_ARRAY_SIZE) ?
173 Integer.MAX_VALUE :
174 MAX_ARRAY_SIZE;
175 }
176
177 /**
178 * Returns the number of elements in this list.
179 *
180 * @return the number of elements in this list
181 */
182 public int size() {
183 return size;
184 }
185
186 /**
187 * Returns <tt>true</tt> if this list contains no elements.
188 *
189 * @return <tt>true</tt> if this list contains no elements
190 */
191 public boolean isEmpty() {
192 return size == 0;
193 }
194
195 /**
196 * Returns <tt>true</tt> if this list contains the specified element.
197 * More formally, returns <tt>true</tt> if and only if this list contains
198 * at least one element <tt>e</tt> such that
199 * <tt>(o==null ? e==null : o.equals(e))</tt>.
200 *
201 * @param o element whose presence in this list is to be tested
202 * @return <tt>true</tt> if this list contains the specified element
203 */
204 public boolean contains(Object o) {
205 return indexOf(o) >= 0;
206 }
207
208 /**
209 * Returns the index of the first occurrence of the specified element
210 * in this list, or -1 if this list does not contain the element.
211 * More formally, returns the lowest index <tt>i</tt> such that
212 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
213 * or -1 if there is no such index.
214 */
215 public int indexOf(Object o) {
216 if (o == null) {
217 for (int i = 0; i < size; i++)
218 if (elementData[i] == null)
219 return i;
220 } else {
221 for (int i = 0; i < size; i++)
222 if (o.equals(elementData[i]))
223 return i;
224 }
225 return -1;
226 }
227
228 /**
229 * Returns the index of the last occurrence of the specified element
230 * in this list, or -1 if this list does not contain the element.
231 * More formally, returns the highest index <tt>i</tt> such that
232 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
233 * or -1 if there is no such index.
234 */
235 public int lastIndexOf(Object o) {
236 if (o == null) {
237 for (int i = size - 1; i >= 0; i--)
238 if (elementData[i] == null)
239 return i;
240 } else {
241 for (int i = size - 1; i >= 0; i--)
242 if (o.equals(elementData[i]))
243 return i;
244 }
245 return -1;
246 }
247
248 /**
249 * Returns a shallow copy of this <tt>Devices</tt> instance. (The
250 * elements themselves are not copied.)
251 *
252 * @return a clone of this <tt>Devices</tt> instance
253 */
254 public Object clone() {
255 try {
256 Devices v = (Devices) super.clone();
257 v.elementData = Arrays.copyOf(elementData, size);
258 v.modCount = 0;
259 return v;
260 } catch (CloneNotSupportedException e) {
261 // this shouldn't happen, since we are Cloneable
262 throw new InternalError(e);
263 }
264 }
265
266 /**
267 * Returns an array containing all of the elements in this list
268 * in proper sequence (from first to last element).
269 * <p>
270 * <p>The returned array will be "safe" in that no references to it are
271 * maintained by this list. (In other words, this method must allocate
272 * a new array). The caller is thus free to modify the returned array.
273 * <p>
274 * <p>This method acts as bridge between array-based and collection-based
275 * APIs.
276 *
277 * @return an array containing all of the elements in this list in
278 * proper sequence
279 */
280 public Object[] toArray() {
281 return Arrays.copyOf(elementData, size);
282 }
283
284 /**
285 * Returns an array containing all of the elements in this list in proper
286 * sequence (from first to last element); the runtime type of the returned
287 * array is that of the specified array. If the list fits in the
288 * specified array, it is returned therein. Otherwise, a new array is
289 * allocated with the runtime type of the specified array and the size of
290 * this list.
291 * <p>
292 * <p>If the list fits in the specified array with room to spare
293 * (i.e., the array has more elements than the list), the element in
294 * the array immediately following the end of the collection is set to
295 * <tt>null</tt>. (This is useful in determining the length of the
296 * list <i>only</i> if the caller knows that the list does not contain
297 * any null elements.)
298 *
299 * @param a the array into which the elements of the list are to
300 * be stored, if it is big enough; otherwise, a new array of the
301 * same runtime type is allocated for this purpose.
302 * @return an array containing the elements of the list
303 * @throws ArrayStoreException if the runtime type of the specified array
304 * is not a supertype of the runtime type of every element in
305 * this list
306 * @throws NullPointerException if the specified array is null
307 */
308 @SuppressWarnings("unchecked")
309 public <T> T[] toArray(T[] a) {
310 if (a.length < size)
311 // Make a new array of a's runtime type, but my contents:
312 return (T[]) Arrays.copyOf(elementData, size, a.getClass());
313 System.arraycopy(elementData, 0, a, 0, size);
314 if (a.length > size)
315 a[size] = null;
316 return a;
317 }
318
319 // Positional Access Operations
320
321 @SuppressWarnings("unchecked")
322 Device elementData(int index) {
323 return (Device) elementData[index];
324 }
325
326 /**
327 * Returns the element at the specified position in this list.
328 *
329 * @param index index of the element to return
330 * @return the element at the specified position in this list
331 * @throws IndexOutOfBoundsException {@inheritDoc}
332 */
333 public Device get(int index) {
334 rangeCheck(index);
335
336 return elementData(index);
337 }
338
339 /**
340 * Replaces the element at the specified position in this list with
341 * the specified element.
342 *
343 * @param index index of the element to replace
344 * @param element element to be stored at the specified position
345 * @return the element previously at the specified position
346 * @throws IndexOutOfBoundsException {@inheritDoc}
347 */
348 public Device set(int index, Device element) {
349 rangeCheck(index);
350
351 Device oldValue = elementData(index);
352 elementData[index] = element;
353 return oldValue;
354 }
355
356 /**
357 * Appends the specified element to the end of this list.
358 *
359 * @param e element to be appended to this list
360 * @return <tt>true</tt> (as specified by {@link Collection#add})
361 */
362 public boolean add(Device e) {
363 ensureCapacityInternal(size + 1); // Increments modCount!!
364 elementData[size++] = e;
365 return true;
366 }
367
368 /**
369 * Inserts the specified element at the specified position in this
370 * list. Shifts the element currently at that position (if any) and
371 * any subsequent elements to the right (adds one to their indices).
372 *
373 * @param index index at which the specified element is to be inserted
374 * @param element element to be inserted
375 * @throws IndexOutOfBoundsException {@inheritDoc}
376 */
377 public void add(int index, Device element) {
378 rangeCheckForAdd(index);
379
380 ensureCapacityInternal(size + 1); // Increments modCount!!
381 System.arraycopy(elementData, index, elementData, index + 1,
382 size - index);
383 elementData[index] = element;
384 size++;
385 }
386
387 /**
388 * Removes the element at the specified position in this list.
389 * Shifts any subsequent elements to the left (subtracts one from their
390 * indices).
391 *
392 * @param index the index of the element to be removed
393 * @return the element that was removed from the list
394 * @throws IndexOutOfBoundsException {@inheritDoc}
395 */
396 public Device remove(int index) {
397 rangeCheck(index);
398
399 modCount++;
400 Device oldValue = elementData(index);
401
402 int numMoved = size - index - 1;
403 if (numMoved > 0)
404 System.arraycopy(elementData, index + 1, elementData, index,
405 numMoved);
406 elementData[--size] = null; // clear to let GC do its work
407
408 return oldValue;
409 }
410
411 /**
412 * Removes the first occurrence of the specified element from this list,
413 * if it is present. If the list does not contain the element, it is
414 * unchanged. More formally, removes the element with the lowest index
415 * <tt>i</tt> such that
416 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
417 * (if such an element exists). Returns <tt>true</tt> if this list
418 * contained the specified element (or equivalently, if this list
419 * changed as a result of the call).
420 *
421 * @param o element to be removed from this list, if present
422 * @return <tt>true</tt> if this list contained the specified element
423 */
424 public boolean remove(Object o) {
425 if (o == null) {
426 for (int index = 0; index < size; index++)
427 if (elementData[index] == null) {
428 fastRemove(index);
429 return true;
430 }
431 } else {
432 for (int index = 0; index < size; index++)
433 if (o.equals(elementData[index])) {
434 fastRemove(index);
435 return true;
436 }
437 }
438 return false;
439 }
440
441 @Override
442 public boolean containsAll(Collection<?> c) {
443 return false;
444 }
445
446 /*
447 * Private remove method that skips bounds checking and does not
448 * return the value removed.
449 */
450 private void fastRemove(int index) {
451 modCount++;
452 int numMoved = size - index - 1;
453 if (numMoved > 0)
454 System.arraycopy(elementData, index + 1, elementData, index,
455 numMoved);
456 elementData[--size] = null; // clear to let GC do its work
457 }
458
459 /**
460 * Removes all of the elements from this list. The list will
461 * be empty after this call returns.
462 */
463 public void clear() {
464 modCount++;
465
466 // clear to let GC do its work
467 for (int i = 0; i < size; i++)
468 elementData[i] = null;
469
470 size = 0;
471 }
472
473 /**
474 * Appends all of the elements in the specified collection to the end of
475 * this list, in the order that they are returned by the
476 * specified collection's Iterator. The behavior of this operation is
477 * undefined if the specified collection is modified while the operation
478 * is in progress. (This implies that the behavior of this call is
479 * undefined if the specified collection is this list, and this
480 * list is nonempty.)
481 *
482 * @param c collection containing elements to be added to this list
483 * @return <tt>true</tt> if this list changed as a result of the call
484 * @throws NullPointerException if the specified collection is null
485 */
486 public boolean addAll(Collection<? extends Device> c) {
487 Object[] a = c.toArray();
488 int numNew = a.length;
489 ensureCapacityInternal(size + numNew); // Increments modCount
490 System.arraycopy(a, 0, elementData, size, numNew);
491 size += numNew;
492 return numNew != 0;
493 }
494
495 /**
496 * Inserts all of the elements in the specified collection into this
497 * list, starting at the specified position. Shifts the element
498 * currently at that position (if any) and any subsequent elements to
499 * the right (increases their indices). The new elements will appear
500 * in the list in the order that they are returned by the
501 * specified collection's iterator.
502 *
503 * @param index index at which to insert the first element from the
504 * specified collection
505 * @param c collection containing elements to be added to this list
506 * @return <tt>true</tt> if this list changed as a result of the call
507 * @throws IndexOutOfBoundsException {@inheritDoc}
508 * @throws NullPointerException if the specified collection is null
509 */
510 public boolean addAll(int index, Collection<? extends Device> c) {
511 rangeCheckForAdd(index);
512
513 Object[] a = c.toArray();
514 int numNew = a.length;
515 ensureCapacityInternal(size + numNew); // Increments modCount
516
517 int numMoved = size - index;
518 if (numMoved > 0)
519 System.arraycopy(elementData, index, elementData, index + numNew,
520 numMoved);
521
522 System.arraycopy(a, 0, elementData, index, numNew);
523 size += numNew;
524 return numNew != 0;
525 }
526
527 /**
528 * Removes from this list all of the elements whose index is between
529 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
530 * Shifts any succeeding elements to the left (reduces their index).
531 * This call shortens the list by {@code (toIndex - fromIndex)} elements.
532 * (If {@code toIndex==fromIndex}, this operation has no effect.)
533 *
534 * @throws IndexOutOfBoundsException if {@code fromIndex} or
535 * {@code toIndex} is out of range
536 * ({@code fromIndex < 0 ||
537 * fromIndex >= size() ||
538 * toIndex > size() ||
539 * toIndex < fromIndex})
540 */
541 protected void removeRange(int fromIndex, int toIndex) {
542 modCount++;
543 int numMoved = size - toIndex;
544 System.arraycopy(elementData, toIndex, elementData, fromIndex,
545 numMoved);
546
547 // clear to let GC do its work
548 int newSize = size - (toIndex - fromIndex);
549 for (int i = newSize; i < size; i++) {
550 elementData[i] = null;
551 }
552 size = newSize;
553 }
554
555 /**
556 * Checks if the given index is in range. If not, throws an appropriate
557 * runtime exception. This method does *not* check if the index is
558 * negative: It is always used immediately prior to an array access,
559 * which throws an ArrayIndexOutOfBoundsException if index is negative.
560 */
561 private void rangeCheck(int index) {
562 if (index >= size)
563 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
564 }
565
566 /**
567 * A version of rangeCheck used by add and addAll.
568 */
569 private void rangeCheckForAdd(int index) {
570 if (index > size || index < 0)
571 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
572 }
573
574 /**
575 * Constructs an IndexOutOfBoundsException detail message.
576 * Of the many possible refactorings of the error handling code,
577 * this "outlining" performs best with both server and client VMs.
578 */
579 private String outOfBoundsMsg(int index) {
580 return "Index: " + index + ", Size: " + size;
581 }
582
583 /**
584 * Removes from this list all of its elements that are contained in the
585 * specified collection.
586 *
587 * @param c collection containing elements to be removed from this list
588 * @return {@code true} if this list changed as a result of the call
589 * @throws ClassCastException if the class of an element of this list
590 * is incompatible with the specified collection
591 * (<a href="Collection.html#optional-restrictions">optional</a>)
592 * @throws NullPointerException if this list contains a null element and the
593 * specified collection does not permit null elements
594 * (<a href="Collection.html#optional-restrictions">optional</a>),
595 * or if the specified collection is null
596 * @see Collection#contains(Object)
597 */
598 public boolean removeAll(Collection<?> c) {
599 Objects.requireNonNull(c);
600 return batchRemove(c, false);
601 }
602
603 /**
604 * Retains only the elements in this list that are contained in the
605 * specified collection. In other words, removes from this list all
606 * of its elements that are not contained in the specified collection.
607 *
608 * @param c collection containing elements to be retained in this list
609 * @return {@code true} if this list changed as a result of the call
610 * @throws ClassCastException if the class of an element of this list
611 * is incompatible with the specified collection
612 * (<a href="Collection.html#optional-restrictions">optional</a>)
613 * @throws NullPointerException if this list contains a null element and the
614 * specified collection does not permit null elements
615 * (<a href="Collection.html#optional-restrictions">optional</a>),
616 * or if the specified collection is null
617 * @see Collection#contains(Object)
618 */
619 public boolean retainAll(Collection<?> c) {
620 Objects.requireNonNull(c);
621 return batchRemove(c, true);
622 }
623
624 private boolean batchRemove(Collection<?> c, boolean complement) {
625 final Object[] elementData = this.elementData;
626 int r = 0, w = 0;
627 boolean modified = false;
628 try {
629 for (; r < size; r++)
630 if (c.contains(elementData[r]) == complement)
631 elementData[w++] = elementData[r];
632 } finally {
633 // Preserve behavioral compatibility with AbstractCollection,
634 // even if c.contains() throws.
635 if (r != size) {
636 System.arraycopy(elementData, r,
637 elementData, w,
638 size - r);
639 w += size - r;
640 }
641 if (w != size) {
642 // clear to let GC do its work
643 for (int i = w; i < size; i++)
644 elementData[i] = null;
645 modCount += size - w;
646 size = w;
647 modified = true;
648 }
649 }
650 return modified;
651 }
652
653 /**
654 * Save the state of the <tt>Devices</tt> instance to a stream (that
655 * is, serialize it).
656 *
657 * @serialData The length of the array backing the <tt>Devices</tt>
658 * instance is emitted (int), followed by all of its elements
659 * (each an <tt>Object</tt>) in the proper order.
660 */
661 private void writeObject(java.io.ObjectOutputStream s)
662 throws java.io.IOException {
663 // Write out element count, and any hidden stuff
664 int expectedModCount = modCount;
665 s.defaultWriteObject();
666
667 // Write out size as capacity for behavioural compatibility with clone()
668 s.writeInt(size);
669
670 // Write out all elements in the proper order.
671 for (int i = 0; i < size; i++) {
672 s.writeObject(elementData[i]);
673 }
674
675 if (modCount != expectedModCount) {
676 throw new ConcurrentModificationException();
677 }
678 }
679
680 /**
681 * Reconstitute the <tt>Devices</tt> instance from a stream (that is,
682 * deserialize it).
683 */
684 private void readObject(java.io.ObjectInputStream s)
685 throws java.io.IOException, ClassNotFoundException {
686 elementData = EMPTY_ELEMENTDATA;
687
688 // Read in size, and any hidden stuff
689 s.defaultReadObject();
690
691 // Read in capacity
692 s.readInt(); // ignored
693
694 if (size > 0) {
695 // be like clone(), allocate array based upon size not capacity
696 ensureCapacityInternal(size);
697
698 Object[] a = elementData;
699 // Read in all elements in the proper order.
700 for (int i = 0; i < size; i++) {
701 a[i] = s.readObject();
702 }
703 }
704 }
705
706 /**
707 * Returns a list iterator over the elements in this list (in proper
708 * sequence), starting at the specified position in the list.
709 * The specified index indicates the first element that would be
710 * returned by an initial call to {@link ListIterator#next next}.
711 * An initial call to {@link ListIterator#previous previous} would
712 * return the element with the specified index minus one.
713 * <p>
714 * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
715 *
716 * @throws IndexOutOfBoundsException {@inheritDoc}
717 */
718 public ListIterator<Device> listIterator(int index) {
719 if (index < 0 || index > size)
720 throw new IndexOutOfBoundsException("Index: " + index);
721 return new Devices.ListItr(index);
722 }
723
724 /**
725 * Returns a list iterator over the elements in this list (in proper
726 * sequence).
727 * <p>
728 * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
729 *
730 * @see #listIterator(int)
731 */
732 public ListIterator<Device> listIterator() {
733 return new Devices.ListItr(0);
734 }
735
736 /**
737 * Returns an iterator over the elements in this list in proper sequence.
738 * <p>
739 * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
740 *
741 * @return an iterator over the elements in this list in proper sequence
742 */
743 public Iterator<Device> iterator() {
744 return new Devices.Itr();
745 }
746
747 /**
748 * An optimized version of AbstractList.Itr
749 */
750 private class Itr implements Iterator<Device> {
751 int cursor; // index of next element to return
752 int lastRet = -1; // index of last element returned; -1 if no such
753 int expectedModCount = modCount;
754
755 public boolean hasNext() {
756 return cursor != size;
757 }
758
759 @SuppressWarnings("unchecked")
760 public Device next() {
761 checkForComodification();
762 int i = cursor;
763 if (i >= size)
764 throw new NoSuchElementException();
765 Object[] elementData = Devices.this.elementData;
766 if (i >= elementData.length)
767 throw new ConcurrentModificationException();
768 cursor = i + 1;
769 return (Device) elementData[lastRet = i];
770 }
771
772 public void remove() {
773 if (lastRet < 0)
774 throw new IllegalStateException();
775 checkForComodification();
776
777 try {
778 Devices.this.remove(lastRet);
779 cursor = lastRet;
780 lastRet = -1;
781 expectedModCount = modCount;
782 } catch (IndexOutOfBoundsException ex) {
783 throw new ConcurrentModificationException();
784 }
785 }
786
787 @Override
788 @SuppressWarnings("unchecked")
789 public void forEachRemaining(Consumer<? super Device> consumer) {
790 Objects.requireNonNull(consumer);
791 final int size = Devices.this.size;
792 int i = cursor;
793 if (i >= size) {
794 return;
795 }
796 final Object[] elementData = Devices.this.elementData;
797 if (i >= elementData.length) {
798 throw new ConcurrentModificationException();
799 }
800 while (i != size && modCount == expectedModCount) {
801 consumer.accept((Device) elementData[i++]);
802 }
803 // update once at end of iteration to reduce heap write traffic
804 cursor = i;
805 lastRet = i - 1;
806 checkForComodification();
807 }
808
809 final void checkForComodification() {
810 if (modCount != expectedModCount)
811 throw new ConcurrentModificationException();
812 }
813 }
814
815 /**
816 * An optimized version of AbstractList.ListItr
817 */
818 private class ListItr extends Devices.Itr implements ListIterator<Device> {
819 ListItr(int index) {
820 super();
821 cursor = index;
822 }
823
824 public boolean hasPrevious() {
825 return cursor != 0;
826 }
827
828 public int nextIndex() {
829 return cursor;
830 }
831
832 public int previousIndex() {
833 return cursor - 1;
834 }
835
836 @SuppressWarnings("unchecked")
837 public Device previous() {
838 checkForComodification();
839 int i = cursor - 1;
840 if (i < 0)
841 throw new NoSuchElementException();
842 Object[] elementData = Devices.this.elementData;
843 if (i >= elementData.length)
844 throw new ConcurrentModificationException();
845 cursor = i;
846 return (Device) elementData[lastRet = i];
847 }
848
849 public void set(Device e) {
850 if (lastRet < 0)
851 throw new IllegalStateException();
852 checkForComodification();
853
854 try {
855 Devices.this.set(lastRet, e);
856 } catch (IndexOutOfBoundsException ex) {
857 throw new ConcurrentModificationException();
858 }
859 }
860
861 public void add(Device e) {
862 checkForComodification();
863
864 try {
865 int i = cursor;
866 Devices.this.add(i, e);
867 cursor = i + 1;
868 lastRet = -1;
869 expectedModCount = modCount;
870 } catch (IndexOutOfBoundsException ex) {
871 throw new ConcurrentModificationException();
872 }
873 }
874 }
875
876 /**
877 * Returns a view of the portion of this list between the specified
878 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. (If
879 * {@code fromIndex} and {@code toIndex} are equal, the returned list is
880 * empty.) The returned list is backed by this list, so non-structural
881 * changes in the returned list are reflected in this list, and vice-versa.
882 * The returned list supports all of the optional list operations.
883 * <p>
884 * <p>This method eliminates the need for explicit range operations (of
885 * the sort that commonly exist for arrays). Any operation that expects
886 * a list can be used as a range operation by passing a subList view
887 * instead of a whole list. For example, the following idiom
888 * removes a range of elements from a list:
889 * <pre>
890 * list.subList(from, to).clear();
891 * </pre>
892 * Similar idioms may be constructed for {@link #indexOf(Object)} and
893 * {@link #lastIndexOf(Object)}, and all of the algorithms in the
894 * {@link Collections} class can be applied to a subList.
895 * <p>
896 * <p>The semantics of the list returned by this method become undefined if
897 * the backing list (i.e., this list) is <i>structurally modified</i> in
898 * any way other than via the returned list. (Structural modifications are
899 * those that change the size of this list, or otherwise perturb it in such
900 * a fashion that iterations in progress may yield incorrect results.)
901 *
902 * @throws IndexOutOfBoundsException {@inheritDoc}
903 * @throws IllegalArgumentException {@inheritDoc}
904 */
905 public List<Device> subList(int fromIndex, int toIndex) {
906 subListRangeCheck(fromIndex, toIndex, size);
907 return new Devices.SubList(this, 0, fromIndex, toIndex);
908 }
909
910 static void subListRangeCheck(int fromIndex, int toIndex, int size) {
911 if (fromIndex < 0)
912 throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
913 if (toIndex > size)
914 throw new IndexOutOfBoundsException("toIndex = " + toIndex);
915 if (fromIndex > toIndex)
916 throw new IllegalArgumentException("fromIndex(" + fromIndex +
917 ") > toIndex(" + toIndex + ")");
918 }
919
920 private class SubList extends AbstractList<Device> implements RandomAccess {
921 private final AbstractList<Device> parent;
922 private final int parentOffset;
923 private final int offset;
924 int size;
925
926 SubList(AbstractList<Device> parent,
927 int offset, int fromIndex, int toIndex) {
928 this.parent = parent;
929 this.parentOffset = fromIndex;
930 this.offset = offset + fromIndex;
931 this.size = toIndex - fromIndex;
932 this.modCount = Devices.this.modCount;
933 }
934
935 public Device set(int index, Device e) {
936 rangeCheck(index);
937 checkForComodification();
938 Device oldValue = Devices.this.elementData(offset + index);
939 Devices.this.elementData[offset + index] = e;
940 return oldValue;
941 }
942
943 public Device get(int index) {
944 rangeCheck(index);
945 checkForComodification();
946 return Devices.this.elementData(offset + index);
947 }
948
949 public int size() {
950 checkForComodification();
951 return this.size;
952 }
953
954 public void add(int index, Device e) {
955 rangeCheckForAdd(index);
956 checkForComodification();
957 parent.add(parentOffset + index, e);
958// this.modCount = parent.modCount;
959 this.size++;
960 }
961
962 public Device remove(int index) {
963 rangeCheck(index);
964 checkForComodification();
965 Device result = parent.remove(parentOffset + index);
966// this.modCount = parent.modCount;
967 this.size--;
968 return result;
969 }
970
971 protected void removeRange(int fromIndex, int toIndex) {
972 checkForComodification(); //??? lol
973 // parent.removeRange(parentOffset + fromIndex, parentOffset + toIndex);
974 // this.modCount = parent.modCount;
975 for (int i = fromIndex; i < toIndex; i++) remove(i);
976 this.size -= toIndex - fromIndex;
977 }
978
979 public boolean addAll(Collection<? extends Device> c) {
980 return addAll(this.size, c);
981 }
982
983 public boolean addAll(int index, Collection<? extends Device> c) {
984 rangeCheckForAdd(index);
985 int cSize = c.size();
986 if (cSize == 0)
987 return false;
988
989 checkForComodification();
990 parent.addAll(parentOffset + index, c);
991// this.modCount = parent.modCount;
992 this.size += cSize;
993 return true;
994 }
995
996 public Iterator<Device> iterator() {
997 return listIterator();
998 }
999
1000 public ListIterator<Device> listIterator(final int index) {
1001 checkForComodification();
1002 rangeCheckForAdd(index);
1003 final int offset = this.offset;
1004
1005 return new ListIterator<Device>() {
1006 int cursor = index;
1007 int lastRet = -1;
1008 int expectedModCount = Devices.this.modCount;
1009
1010 public boolean hasNext() {
1011 return cursor != Devices.SubList.this.size;
1012 }
1013
1014 @SuppressWarnings("unchecked")
1015 public Device next() {
1016 checkForComodification();
1017 int i = cursor;
1018 if (i >= Devices.SubList.this.size)
1019 throw new NoSuchElementException();
1020 Object[] elementData = Devices.this.elementData;
1021 if (offset + i >= elementData.length)
1022 throw new ConcurrentModificationException();
1023 cursor = i + 1;
1024 return (Device) elementData[offset + (lastRet = i)];
1025 }
1026
1027 public boolean hasPrevious() {
1028 return cursor != 0;
1029 }
1030
1031 @SuppressWarnings("unchecked")
1032 public Device previous() {
1033 checkForComodification();
1034 int i = cursor - 1;
1035 if (i < 0)
1036 throw new NoSuchElementException();
1037 Object[] elementData = Devices.this.elementData;
1038 if (offset + i >= elementData.length)
1039 throw new ConcurrentModificationException();
1040 cursor = i;
1041 return (Device) elementData[offset + (lastRet = i)];
1042 }
1043
1044 @SuppressWarnings("unchecked")
1045 public void forEachRemaining(Consumer<? super Device> consumer) {
1046 Objects.requireNonNull(consumer);
1047 final int size = Devices.SubList.this.size;
1048 int i = cursor;
1049 if (i >= size) {
1050 return;
1051 }
1052 final Object[] elementData = Devices.this.elementData;
1053 if (offset + i >= elementData.length) {
1054 throw new ConcurrentModificationException();
1055 }
1056 while (i != size && modCount == expectedModCount) {
1057 consumer.accept((Device) elementData[offset + (i++)]);
1058 }
1059 // update once at end of iteration to reduce heap write traffic
1060 lastRet = cursor = i;
1061 checkForComodification();
1062 }
1063
1064 public int nextIndex() {
1065 return cursor;
1066 }
1067
1068 public int previousIndex() {
1069 return cursor - 1;
1070 }
1071
1072 public void remove() {
1073 if (lastRet < 0)
1074 throw new IllegalStateException();
1075 checkForComodification();
1076
1077 try {
1078 Devices.SubList.this.remove(lastRet);
1079 cursor = lastRet;
1080 lastRet = -1;
1081 expectedModCount = Devices.this.modCount;
1082 } catch (IndexOutOfBoundsException ex) {
1083 throw new ConcurrentModificationException();
1084 }
1085 }
1086
1087 public void set(Device e) {
1088 if (lastRet < 0)
1089 throw new IllegalStateException();
1090 checkForComodification();
1091
1092 try {
1093 Devices.this.set(offset + lastRet, e);
1094 } catch (IndexOutOfBoundsException ex) {
1095 throw new ConcurrentModificationException();
1096 }
1097 }
1098
1099 public void add(Device e) {
1100 checkForComodification();
1101
1102 try {
1103 int i = cursor;
1104 Devices.SubList.this.add(i, e);
1105 cursor = i + 1;
1106 lastRet = -1;
1107 expectedModCount = Devices.this.modCount;
1108 } catch (IndexOutOfBoundsException ex) {
1109 throw new ConcurrentModificationException();
1110 }
1111 }
1112
1113 final void checkForComodification() {
1114 if (expectedModCount != Devices.this.modCount)
1115 throw new ConcurrentModificationException();
1116 }
1117 };
1118 }
1119
1120 public List<Device> subList(int fromIndex, int toIndex) {
1121 subListRangeCheck(fromIndex, toIndex, size);
1122 return new Devices.SubList(this, offset, fromIndex, toIndex);
1123 }
1124
1125 private void rangeCheck(int index) {
1126 if (index < 0 || index >= this.size)
1127 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
1128 }
1129
1130 private void rangeCheckForAdd(int index) {
1131 if (index < 0 || index > this.size)
1132 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
1133 }
1134
1135 private String outOfBoundsMsg(int index) {
1136 return "Index: " + index + ", Size: " + this.size;
1137 }
1138
1139 private void checkForComodification() {
1140 if (Devices.this.modCount != this.modCount)
1141 throw new ConcurrentModificationException();
1142 }
1143
1144 public Spliterator<Device> spliterator() {
1145 checkForComodification();
1146 return new Devices.ArrayListSpliterator<Device>(Devices.this, offset,
1147 offset + this.size, this.modCount);
1148 }
1149 }
1150
1151 @Override
1152 public void forEach(Consumer<? super Device> action) {
1153 Objects.requireNonNull(action);
1154 final int expectedModCount = modCount;
1155 @SuppressWarnings("unchecked") final Device[] elementData = (Device[]) this.elementData;
1156 final int size = this.size;
1157 for (int i = 0; modCount == expectedModCount && i < size; i++) {
1158 action.accept(elementData[i]);
1159 }
1160 if (modCount != expectedModCount) {
1161 throw new ConcurrentModificationException();
1162 }
1163 }
1164
1165 /**
1166 * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
1167 * and <em>fail-fast</em> {@link Spliterator} over the elements in this
1168 * list.
1169 * <p>
1170 * <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
1171 * {@link Spliterator#SUBSIZED}, and {@link Spliterator#ORDERED}.
1172 * Overriding implementations should document the reporting of additional
1173 * characteristic values.
1174 *
1175 * @return a {@code Spliterator} over the elements in this list
1176 * @since 1.8
1177 */
1178 @Override
1179 public Spliterator<Device> spliterator() {
1180 return new Devices.ArrayListSpliterator<>(this, 0, -1, 0);
1181 }
1182
1183 /**
1184 * Index-based split-by-two, lazily initialized Spliterator
1185 */
1186 static final class ArrayListSpliterator<Device> implements Spliterator<Device> {
1187
1188 /*
1189 * If ArrayLists were immutable, or structurally immutable (no
1190 * adds, removes, etc), we could implement their spliterators
1191 * with Arrays.spliterator. Instead we detect as much
1192 * interference during traversal as practical without
1193 * sacrificing much performance. We rely primarily on
1194 * modCounts. These are not guaranteed to detect concurrency
1195 * violations, and are sometimes overly conservative about
1196 * within-thread interference, but detect enough problems to
1197 * be worthwhile in practice. To carry this out, we (1) lazily
1198 * initialize fence and expectedModCount until the latest
1199 * point that we need to commit to the state we are checking
1200 * against; thus improving precision. (This doesn't apply to
1201 * SubLists, that create spliterators with current non-lazy
1202 * values). (2) We perform only a single
1203 * ConcurrentModificationException check at the end of forEach
1204 * (the most performance-sensitive method). When using forEach
1205 * (as opposed to iterators), we can normally only detect
1206 * interference after actions, not before. Further
1207 * CME-triggering checks apply to all other possible
1208 * violations of assumptions for example null or too-small
1209 * elementData array given its size(), that could only have
1210 * occurred due to interference. This allows the inner loop
1211 * of forEach to run without any further checks, and
1212 * simplifies lambda-resolution. While this does entail a
1213 * number of checks, note that in the common case of
1214 * list.stream().forEach(a), no checks or other computation
1215 * occur anywhere other than inside forEach itself. The other
1216 * less-often-used methods cannot take advantage of most of
1217 * these streamlinings.
1218 */
1219
1220 private final Devices list;
1221 private int index; // current index, modified on advance/split
1222 private int fence; // -1 until used; then one past last index
1223 private int expectedModCount; // initialized when fence set
1224
1225 /**
1226 * Create new spliterator covering the given range
1227 */
1228 ArrayListSpliterator(Devices list, int origin, int fence,
1229 int expectedModCount) {
1230 this.list = list; // OK if null unless traversed
1231 this.index = origin;
1232 this.fence = fence;
1233 this.expectedModCount = expectedModCount;
1234 }
1235
1236 private int getFence() { // initialize fence to size on first use
1237 int hi; // (a specialized variant appears in method forEach)
1238 Devices lst;
1239 if ((hi = fence) < 0) {
1240 if ((lst = list) == null)
1241 hi = fence = 0;
1242 else {
1243 expectedModCount = lst.modCount;
1244 hi = fence = lst.size;
1245 }
1246 }
1247 return hi;
1248 }
1249
1250 public Devices.ArrayListSpliterator<Device> trySplit() {
1251 int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
1252 return (lo >= mid) ? null : // divide range in half unless too small
1253 new Devices.ArrayListSpliterator<Device>(list, lo, index = mid,
1254 expectedModCount);
1255 }
1256
1257 public boolean tryAdvance(Consumer<? super Device> action) {
1258 if (action == null)
1259 throw new NullPointerException();
1260 int hi = getFence(), i = index;
1261 if (i < hi) {
1262 index = i + 1;
1263 @SuppressWarnings("unchecked") Device e = (Device) list.elementData[i];
1264 action.accept(e);
1265 if (list.modCount != expectedModCount)
1266 throw new ConcurrentModificationException();
1267 return true;
1268 }
1269 return false;
1270 }
1271
1272 public void forEachRemaining(Consumer<? super Device> action) {
1273 int i, hi, mc; // hoist accesses and checks from loop
1274 Devices lst;
1275 Object[] a;
1276 if (action == null)
1277 throw new NullPointerException();
1278 if ((lst = list) != null && (a = lst.elementData) != null) {
1279 if ((hi = fence) < 0) {
1280 mc = lst.modCount;
1281 hi = lst.size;
1282 } else
1283 mc = expectedModCount;
1284 if ((i = index) >= 0 && (index = hi) <= a.length) {
1285 for (; i < hi; ++i) {
1286 @SuppressWarnings("unchecked") Device e = (Device) a[i];
1287 action.accept(e);
1288 }
1289 if (lst.modCount == mc)
1290 return;
1291 }
1292 }
1293 throw new ConcurrentModificationException();
1294 }
1295
1296 public long estimateSize() {
1297 return (long) (getFence() - index);
1298 }
1299
1300 public int characteristics() {
1301 return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
1302 }
1303 }
1304
1305 @Override
1306 public boolean removeIf(Predicate<? super Device> filter) {
1307 Objects.requireNonNull(filter);
1308 // figure out which elements are to be removed
1309 // any exception thrown from the filter predicate at this stage
1310 // will leave the collection unmodified
1311 int removeCount = 0;
1312 final BitSet removeSet = new BitSet(size);
1313 final int expectedModCount = modCount;
1314 final int size = this.size;
1315 for (int i = 0; modCount == expectedModCount && i < size; i++) {
1316 @SuppressWarnings("unchecked") final Device element = (Device) elementData[i];
1317 if (filter.test(element)) {
1318 removeSet.set(i);
1319 removeCount++;
1320 }
1321 }
1322 if (modCount != expectedModCount) {
1323 throw new ConcurrentModificationException();
1324 }
1325
1326 // shift surviving elements left over the spaces left by removed elements
1327 final boolean anyToRemove = removeCount > 0;
1328 if (anyToRemove) {
1329 final int newSize = size - removeCount;
1330 for (int i = 0, j = 0; (i < size) && (j < newSize); i++, j++) {
1331 i = removeSet.nextClearBit(i);
1332 elementData[j] = elementData[i];
1333 }
1334 for (int k = newSize; k < size; k++) {
1335 elementData[k] = null; // Let gc do its work
1336 }
1337 this.size = newSize;
1338 if (modCount != expectedModCount) {
1339 throw new ConcurrentModificationException();
1340 }
1341 modCount++;
1342 }
1343
1344 return anyToRemove;
1345 }
1346
1347 @Override
1348 @SuppressWarnings("unchecked")
1349 public void replaceAll(UnaryOperator<Device> operator) {
1350 Objects.requireNonNull(operator);
1351 final int expectedModCount = modCount;
1352 final int size = this.size;
1353 for (int i = 0; modCount == expectedModCount && i < size; i++) {
1354 elementData[i] = operator.apply((Device) elementData[i]);
1355 }
1356 if (modCount != expectedModCount) {
1357 throw new ConcurrentModificationException();
1358 }
1359 modCount++;
1360 }
1361
1362 @Override
1363 @SuppressWarnings("unchecked")
1364 public void sort(Comparator<? super Device> c) {
1365 final int expectedModCount = modCount;
1366 Arrays.sort((Device[]) elementData, 0, size, c);
1367 if (modCount != expectedModCount) {
1368 throw new ConcurrentModificationException();
1369 }
1370 modCount++;
1371 }
1372
1373 //from lab5.devices.Devices
1374
1375 private static class PowerConsComp implements Comparator<Device> {
1376 @Override
1377 public strictfp int compare(Device d1, Device d2) {
1378 return d1.getPowerCons() < d2.getPowerCons() ? 1 : -1;
1379 }
1380 }
1381
1382 public void sortByPowerCons() {
1383 this.sort(new PowerConsComp());
1384 }
1385
1386 public Device findFirstInRadRange(int radFrom, int radTo) { //radiation-based device search
1387 for (Device d : this) {
1388 if (radFrom <= d.getRadiation() && d.getRadiation() <= radTo)
1389 return d; //found!
1390 }
1391 return null; //no such
1392 }
1393
1394 @Override
1395 public String toString() {
1396 Iterator<Device> it = iterator();
1397 if (! it.hasNext())
1398 return "[]";
1399
1400 StringBuilder sb = new StringBuilder();
1401 sb.append('[');
1402 for (;;) {
1403 Device d = it.next();
1404 sb.append(d);
1405 if (! it.hasNext())
1406 return sb.append(']').toString();
1407 sb.append(',').append('\n').append(' ');
1408 }
1409 }
1410}