public void removeFromFirst(final int toIndex) {
        int alignedIndex = toIndex + this.firstOffset;
        int toSegmentIndex = alignedIndex >> SEGMENT_SHIFT;

        int toIndexInSeg = alignedIndex & (SEGMENT_SIZE - 1);

        if (toSegmentIndex > 0) {
            this.segments.removeRange(0, toSegmentIndex);
            this.size -= ((toSegmentIndex << SEGMENT_SHIFT) - this.firstOffset);
        }

        Segment<T> firstSeg = this.getFirst();
        if (firstSeg != null) {
            this.size -= firstSeg.removeFromFirst(toIndexInSeg);
            this.firstOffset = firstSeg.offset;
            if (firstSeg.isEmpty()) {
                RecycleUtil.recycle(this.segments.pollFirst());
                this.firstOffset = 0;
            }
        } else {
            this.firstOffset = this.size = 0;
        }
    }
@Test
    public void testRemoveFromFirst() {
        fillList();

        int len = SegmentList.SEGMENT_SIZE - 1;
        this.list.removeFromFirst(len);

        assertEquals(1000 - len, this.list.size());

        for (int i = 0; i < 1000 - len; i++) {
            assertEquals(i + len, (int) this.list.get(i));
        }

        this.list.removeFromFirst(100);
        assertEquals(1000 - len - 100, this.list.size());

        for (int i = 0; i < 1000 - len - 100; i++) {
            assertEquals(i + len + 100, (int) this.list.get(i));
        }

        this.list.removeFromFirst(1000 - len - 100);
        assertTrue(this.list.isEmpty());
        assertEquals(0, this.list.segmentSize());
        assertNull(this.list.peekFirst());
        assertNull(this.list.peekLast());
    }