Skip to content

Commit 6e42b98

Browse files
authored
Merge pull request #5 from mercyblitz/main
Feature 0.1.5
2 parents bd5c4ab + eb2de34 commit 6e42b98

7 files changed

Lines changed: 399 additions & 13 deletions

File tree

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package io.microsphere.collection;
19+
20+
import java.util.ArrayList;
21+
import java.util.EmptyStackException;
22+
import java.util.Stack;
23+
24+
/**
25+
* The {@code Stack} class represents a last-in-first-out
26+
* (LIFO) stack of objects. It extends class {@code Vector} with five
27+
* operations that allow a vector to be treated as a stack. The usual
28+
* {@code push} and {@code pop} operations are provided, as well as a
29+
* method to {@code peek} at the top item on the stack, a method to test
30+
* for whether the stack is {@code empty}, and a method to {@code search}
31+
* the stack for an item and discover how far it is from the top.
32+
* <p>
33+
* The non thread-safe version of {@link Stack}.
34+
*
35+
* @param <E> Type of component elements
36+
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
37+
* @see ArrayList
38+
* @see Stack
39+
* @since 1.0.0
40+
*/
41+
public class ArrayStack<E> extends ArrayList<E> {
42+
43+
private static final long serialVersionUID = -1417040223081465932L;
44+
45+
/**
46+
* Creates an empty Stack.
47+
*/
48+
public ArrayStack() {
49+
this(0);
50+
}
51+
52+
/**
53+
* Constructs a new, empty stack with the specified initial
54+
* capacity.
55+
*
56+
* @param initialCapacity the initial capacity of the stack.
57+
* @throws IllegalArgumentException if the specified initial capacity
58+
* is negative
59+
*/
60+
public ArrayStack(int initialCapacity) {
61+
super(initialCapacity);
62+
}
63+
64+
/**
65+
* Pushes an item onto the top of this stack. This has exactly
66+
* the same effect as: {@link #add(Object)}
67+
*
68+
* @param item the item to be pushed onto this stack.
69+
* @return the {@code item} argument.
70+
* @see ArrayList#add(Object)
71+
*/
72+
public E push(E item) {
73+
super.add(item);
74+
return item;
75+
}
76+
77+
/**
78+
* Removes the object at the top of this stack and returns that
79+
* object as the value of this function.
80+
*
81+
* @return The object at the top of this stack (the last item
82+
* of the {@code ArrayList} object).
83+
* @throws EmptyStackException if this stack is empty.
84+
*/
85+
public E pop() {
86+
E obj;
87+
int len = super.size();
88+
89+
obj = this.peek();
90+
super.remove(len - 1);
91+
return obj;
92+
}
93+
94+
/**
95+
* Looks at the object at the top of this stack without removing it
96+
* from the stack.
97+
*
98+
* @return the object at the top of this stack (the last item
99+
* of the {@code ArrayList} object).
100+
* @throws EmptyStackException if this stack is empty.
101+
*/
102+
public E peek() throws EmptyStackException {
103+
int len = super.size();
104+
if (len == 0)
105+
throw new EmptyStackException();
106+
return super.get(len - 1);
107+
}
108+
109+
/**
110+
* Tests if this stack is empty.
111+
*
112+
* @return {@code true} if and only if this stack contains
113+
* no items; {@code false} otherwise.
114+
*/
115+
public boolean empty() {
116+
return super.isEmpty();
117+
}
118+
119+
/**
120+
* Returns the 1-based position where an object is on this stack.
121+
* If the object {@code o} occurs as an item in this stack, this
122+
* method returns the distance from the top of the stack of the
123+
* occurrence nearest the top of the stack; the topmost item on the
124+
* stack is considered to be at distance {@code 1}. The {@code equals}
125+
* method is used to compare {@code o} to the
126+
* items in this stack.
127+
*
128+
* @param o the desired object.
129+
* @return the 1-based position from the top of the stack where
130+
* the object is located; the return value {@code -1}
131+
* indicates that the object is not on the stack.
132+
*/
133+
public int search(Object o) {
134+
int i = super.lastIndexOf(o);
135+
136+
if (i >= 0) {
137+
return super.size() - i;
138+
}
139+
return -1;
140+
}
141+
}

microsphere-java-core/src/main/java/io/microsphere/collection/CollectionUtils.java

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ public static boolean equals(@Nullable Collection<?> one, @Nullable Collection<?
432432
* </p>
433433
*
434434
* @param collection the collection to which elements are to be added, may be null or empty
435-
* @param values the array of elements to add, may be null
435+
* @param newValues the array of elements to add, may be null
436436
* @param <T> the type of elements in the collection and array
437437
* @return the number of elements successfully added to the collection
438438
*
@@ -449,21 +449,61 @@ public static boolean equals(@Nullable Collection<?> one, @Nullable Collection<?
449449
* int count4 = CollectionUtils.addAll(emptyCollection, "x"); // returns 0
450450
* }</pre>
451451
*/
452-
public static <T> int addAll(@Nullable Collection<T> collection, T... values) {
453-
452+
public static <T> int addAll(@Nullable Collection<T> collection, T... newValues) {
454453
if (collection == null) {
455454
return 0;
456455
}
457456

458-
int size = length(values);
459-
457+
int size = length(newValues);
460458
if (size < 1) {
461459
return 0;
462460
}
463461

464462
int effectedCount = 0;
465463
for (int i = 0; i < size; i++) {
466-
if (collection.add(values[i])) {
464+
if (collection.add(newValues[i])) {
465+
effectedCount++;
466+
}
467+
}
468+
469+
return effectedCount;
470+
}
471+
472+
/**
473+
* Adds all the elements in the specified {@link Iterable} to the given collection.
474+
*
475+
* <p>
476+
* If the provided collection is null or empty, no elements are added, and 0 is returned.
477+
* If the iterable is null or has no elements, 0 is also returned.
478+
* </p>
479+
*
480+
* @param collection the collection to which elements are to be added, may be null or empty
481+
* @param newValues the {@link Iterable} of elements to add, may be null
482+
* @param <T> the type of elements in the collection and iterable
483+
* @return the number of elements successfully added to the collection
484+
*
485+
* <h3>Example Usage</h3>
486+
* <pre>{@code
487+
* Collection<String> collection = new ArrayList<>();
488+
* Iterable<String> values = Arrays.asList("a", "b", "c");
489+
* int count1 = CollectionUtils.addAll(collection, values); // returns 3
490+
*
491+
* int count2 = CollectionUtils.addAll(null, values); // returns 0
492+
*
493+
* int count3 = CollectionUtils.addAll(collection, (Iterable<String>) null); // returns 0
494+
*
495+
* Collection<String> emptyCollection = Collections.emptyList();
496+
* int count4 = CollectionUtils.addAll(emptyCollection, values); // returns 0
497+
* }</pre>
498+
*/
499+
public static <T> int addAll(@Nullable Collection<T> collection, @Nullable Iterable<T> newValues) {
500+
if (collection == null || newValues == null) {
501+
return 0;
502+
}
503+
504+
int effectedCount = 0;
505+
for (T newValue : newValues) {
506+
if (collection.add(newValue)) {
467507
effectedCount++;
468508
}
469509
}

microsphere-java-core/src/main/java/io/microsphere/util/IterableUtils.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@
1717

1818
package io.microsphere.util;
1919

20+
import io.microsphere.annotation.Nonnull;
2021
import io.microsphere.annotation.Nullable;
2122

23+
import java.util.function.Consumer;
24+
2225
import static io.microsphere.util.ClassUtils.isAssignableFrom;
2326

2427
/**
@@ -66,6 +69,56 @@ public static boolean isIterable(@Nullable Class<?> clazz) {
6669
return isAssignableFrom(Iterable.class, clazz);
6770
}
6871

72+
/**
73+
* Iterates over the given {@link Iterable} and applies the provided {@link Consumer} to each element.
74+
*
75+
* <h3>Example Usage</h3>
76+
* <pre>{@code
77+
* List<String> list = Arrays.asList("a", "b", "c");
78+
* IterableUtils.iterate(list, System.out::println);
79+
* // Output:
80+
* // a
81+
* // b
82+
* // c
83+
* }</pre>
84+
*
85+
* @param elements the {@link Iterable} to iterate over
86+
* @param elementConsumer the {@link Consumer} to apply to each element
87+
* @param <E> the type of elements in the {@link Iterable}
88+
*/
89+
public static <E> void iterate(@Nullable Iterable<E> elements, @Nonnull Consumer<E> elementConsumer) {
90+
if (elements != null) {
91+
for (E element : elements) {
92+
elementConsumer.accept(element);
93+
}
94+
}
95+
}
96+
97+
/**
98+
* Iterates over the given {@link Iterable} and applies the provided {@link Consumer} to each element.
99+
* <p>
100+
* This method is equivalent to {@link #iterate(Iterable, Consumer)}.
101+
* </p>
102+
*
103+
* <h3>Example Usage</h3>
104+
* <pre>{@code
105+
* List<String> list = Arrays.asList("a", "b", "c");
106+
* IterableUtils.forEach(list, System.out::println);
107+
* // Output:
108+
* // a
109+
* // b
110+
* // c
111+
* }</pre>
112+
*
113+
* @param elements the {@link Iterable} to iterate over
114+
* @param elementConsumer the {@link Consumer} to apply to each element
115+
* @param <E> the type of elements in the {@link Iterable}
116+
* @see #iterate(Iterable, Consumer)
117+
*/
118+
public static <E> void forEach(@Nullable Iterable<E> elements, @Nonnull Consumer<E> elementConsumer) {
119+
iterate(elements, elementConsumer);
120+
}
121+
69122
private IterableUtils() {
70123
}
71124
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package io.microsphere.collection;
19+
20+
21+
import org.junit.jupiter.api.BeforeEach;
22+
import org.junit.jupiter.api.Test;
23+
24+
import java.util.EmptyStackException;
25+
26+
import static io.microsphere.collection.ListUtils.ofArrayList;
27+
import static org.junit.jupiter.api.Assertions.assertEquals;
28+
import static org.junit.jupiter.api.Assertions.assertFalse;
29+
import static org.junit.jupiter.api.Assertions.assertThrows;
30+
import static org.junit.jupiter.api.Assertions.assertTrue;
31+
32+
/**
33+
* {@link ArrayStack} Test
34+
*
35+
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
36+
* @see ArrayStack
37+
* @since 1.0.0
38+
*/
39+
class ArrayStackTest {
40+
41+
private ArrayStack<String> stack;
42+
43+
@BeforeEach
44+
void setUp() {
45+
this.stack = new ArrayStack<>();
46+
}
47+
48+
@Test
49+
void testPush() {
50+
this.stack.push("A");
51+
assertEquals(ofArrayList("A"), this.stack);
52+
}
53+
54+
@Test
55+
void testPop() {
56+
this.stack.push("A");
57+
assertEquals("A", this.stack.pop());
58+
assertEquals(0, this.stack.size());
59+
}
60+
61+
@Test
62+
void testPopWithoutElement() {
63+
assertThrows(EmptyStackException.class, this.stack::pop);
64+
}
65+
66+
@Test
67+
void testPeek() {
68+
this.stack.push("A");
69+
assertEquals("A", this.stack.peek());
70+
assertEquals(1, this.stack.size());
71+
}
72+
73+
@Test
74+
void testPeekWithoutElement() {
75+
assertThrows(EmptyStackException.class, this.stack::peek);
76+
}
77+
78+
@Test
79+
void testEmpty() {
80+
assertTrue(this.stack.empty());
81+
82+
this.stack.push("A");
83+
assertFalse(this.stack.empty());
84+
}
85+
86+
@Test
87+
void testSearch() {
88+
this.stack.push("A");
89+
90+
assertEquals(1, this.stack.search("A"));
91+
assertEquals(-1, this.stack.search("B"));
92+
}
93+
}

0 commit comments

Comments
 (0)