HHH-16050 StandardStack optimization using custom array implementation
This commit is contained in:
parent
01db71c272
commit
8755129648
|
@ -68,9 +68,9 @@ public class GraphParser extends GraphLanguageParserBaseVisitor {
|
|||
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
|
||||
private final Stack<GraphImplementor<?>> graphStack = new StandardStack<>();
|
||||
private final Stack<AttributeNodeImplementor<?>> attributeNodeStack = new StandardStack<>();
|
||||
private final Stack<SubGraphGenerator> graphSourceStack = new StandardStack<>();
|
||||
private final Stack<GraphImplementor> graphStack = new StandardStack<>( GraphImplementor.class );
|
||||
private final Stack<AttributeNodeImplementor> attributeNodeStack = new StandardStack<>( AttributeNodeImplementor.class );
|
||||
private final Stack<SubGraphGenerator> graphSourceStack = new StandardStack<>(SubGraphGenerator.class);
|
||||
|
||||
public GraphParser(SessionFactoryImplementor sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.internal.util.collections;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
@ -20,120 +20,95 @@ import java.util.function.Function;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Sanne Grinovero
|
||||
* @author Marco Belladelli
|
||||
*/
|
||||
public final class StandardStack<T> implements Stack<T> {
|
||||
private T[] elements;
|
||||
private int top = 0;
|
||||
|
||||
private ArrayDeque<T> internalStack;
|
||||
private static final Object NULL_TOKEN = new Object();
|
||||
private Class<T> type;
|
||||
|
||||
public StandardStack() {
|
||||
public StandardStack(Class<T> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public StandardStack(T initial) {
|
||||
stackInstanceExpected().addFirst( initial );
|
||||
public StandardStack(Class<T> type, T initial) {
|
||||
this( type );
|
||||
push( initial );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void init() {
|
||||
elements = (T[]) Array.newInstance( type, 8 );
|
||||
type = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(T newCurrent) {
|
||||
T toStore = newCurrent;
|
||||
if ( newCurrent == null ) {
|
||||
toStore = (T) NULL_TOKEN;
|
||||
public void push(T e) {
|
||||
if ( elements == null ) {
|
||||
init();
|
||||
}
|
||||
stackInstanceExpected().addFirst( toStore );
|
||||
}
|
||||
|
||||
private Deque<T> stackInstanceExpected() {
|
||||
if ( internalStack == null ) {
|
||||
//"7" picked to use 8, but skipping the odd initialCapacity method
|
||||
internalStack = new ArrayDeque<>( 7 );
|
||||
if ( top == elements.length ) {
|
||||
grow();
|
||||
}
|
||||
return internalStack;
|
||||
elements[top++] = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T pop() {
|
||||
return convert( stackInstanceExpected().removeFirst() );
|
||||
}
|
||||
|
||||
private T convert(final Object internalStoredObject) {
|
||||
if ( internalStoredObject == NULL_TOKEN ) {
|
||||
return null;
|
||||
if ( isEmpty() ) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
return (T) internalStoredObject;
|
||||
T e = elements[--top];
|
||||
elements[top] = null;
|
||||
return e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getCurrent() {
|
||||
if ( internalStack == null ) {
|
||||
if ( isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
return convert( internalStack.peekFirst() );
|
||||
return elements[top - 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getRoot() {
|
||||
if ( internalStack == null ) {
|
||||
if ( isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
return convert( internalStack.peekLast() );
|
||||
return elements[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int depth() {
|
||||
if ( internalStack == null ) {
|
||||
return 0;
|
||||
}
|
||||
return internalStack.size();
|
||||
return top;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
if ( internalStack == null ) {
|
||||
return true;
|
||||
}
|
||||
return internalStack.isEmpty();
|
||||
return top == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if ( internalStack != null ) {
|
||||
internalStack.clear();
|
||||
for ( int i = 0; i < top; i++ ) {
|
||||
elements[i] = null;
|
||||
}
|
||||
top = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRootFirst(Consumer<T> action) {
|
||||
if ( internalStack == null ) {
|
||||
return;
|
||||
}
|
||||
final Iterator<T> iterator = internalStack.descendingIterator();
|
||||
while ( iterator.hasNext() ) {
|
||||
action.accept( iterator.next() );
|
||||
for ( int i = 0; i < top; i++ ) {
|
||||
action.accept( elements[i] );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X findCurrentFirst(Function<T, X> function) {
|
||||
if ( internalStack == null ) {
|
||||
return null;
|
||||
}
|
||||
for (T t : internalStack) {
|
||||
final X result = function.apply(t);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X,Y> X findCurrentFirstWithParameter(Y parameter, BiFunction<T, Y, X> biFunction) {
|
||||
if ( internalStack == null ) {
|
||||
return null;
|
||||
}
|
||||
for ( T t : internalStack ) {
|
||||
final X result = biFunction.apply( t, parameter );
|
||||
for ( int i = top - 1; i >= 0; i-- ) {
|
||||
final X result = function.apply( elements[i] );
|
||||
if ( result != null ) {
|
||||
return result;
|
||||
}
|
||||
|
@ -141,4 +116,20 @@ public final class StandardStack<T> implements Stack<T> {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X, Y> X findCurrentFirstWithParameter(Y parameter, BiFunction<T, Y, X> biFunction) {
|
||||
for ( int i = top - 1; i >= 0; i-- ) {
|
||||
final X result = biFunction.apply( elements[i], parameter );
|
||||
if ( result != null ) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void grow() {
|
||||
final int oldCapacity = elements.length;
|
||||
final int jump = ( oldCapacity < 64 ) ? ( oldCapacity + 2 ) : ( oldCapacity >> 1 );
|
||||
elements = Arrays.copyOf( elements, oldCapacity + jump );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ public class QuerySplitter {
|
|||
private final SqmRoot unmappedPolymorphicFromElement;
|
||||
private final EntityDomainType<R> mappedDescriptor;
|
||||
private final SqmCreationContext creationContext;
|
||||
private final Stack<SqmCreationProcessingState> processingStateStack = new StandardStack<>();
|
||||
private final Stack<SqmCreationProcessingState> processingStateStack = new StandardStack<>( SqmCreationProcessingState.class );
|
||||
|
||||
private Map<NavigablePath, SqmPath> sqmPathCopyMap = new HashMap<>();
|
||||
private Map<SqmFrom, SqmFrom> sqmFromCopyMap = new HashMap<>();
|
||||
|
|
|
@ -300,8 +300,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
private final Stack<DotIdentifierConsumer> dotIdentifierConsumerStack;
|
||||
|
||||
private final Stack<ParameterDeclarationContext> parameterDeclarationContextStack = new StandardStack<>();
|
||||
private final Stack<SqmCreationProcessingState> processingStateStack = new StandardStack<>();
|
||||
private final Stack<ParameterDeclarationContext> parameterDeclarationContextStack = new StandardStack<>( ParameterDeclarationContext.class );
|
||||
private final Stack<SqmCreationProcessingState> processingStateStack = new StandardStack<>( SqmCreationProcessingState.class );
|
||||
|
||||
private final BasicDomainType<Integer> integerDomainType;
|
||||
private final JavaType<List<?>> listJavaType;
|
||||
|
@ -323,7 +323,10 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
this.expectedResultType = expectedResultType;
|
||||
this.creationOptions = creationOptions;
|
||||
this.creationContext = creationContext;
|
||||
this.dotIdentifierConsumerStack = new StandardStack<>( new BasicDotIdentifierConsumer( this ) );
|
||||
this.dotIdentifierConsumerStack = new StandardStack<>(
|
||||
DotIdentifierConsumer.class,
|
||||
new BasicDotIdentifierConsumer( this )
|
||||
);
|
||||
this.parameterStyle = creationOptions.useStrictJpaCompliance()
|
||||
? ParameterStyle.UNKNOWN
|
||||
: ParameterStyle.MIXED;
|
||||
|
|
|
@ -77,8 +77,8 @@ public class DomainResultCreationStateImpl
|
|||
private final LegacyFetchResolverImpl legacyFetchResolver;
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
|
||||
private final Stack<Function<String, FetchBuilder>> fetchBuilderResolverStack = new StandardStack<>( fetchableName -> null );
|
||||
private final Stack<Map.Entry<String, NavigablePath>> relativePathStack = new StandardStack<>();
|
||||
private final Stack<Function> fetchBuilderResolverStack = new StandardStack<>( Function.class, fetchableName -> null );
|
||||
private final Stack<Map.Entry> relativePathStack = new StandardStack<>( Map.Entry.class );
|
||||
private Map<String, LockMode> registeredLockModes;
|
||||
private boolean processingKeyFetches = false;
|
||||
private boolean resolvingCircularFetch;
|
||||
|
@ -356,7 +356,7 @@ public class DomainResultCreationStateImpl
|
|||
}
|
||||
|
||||
final Fetchable fetchable = (Fetchable) identifierMapping;
|
||||
final FetchBuilder explicitFetchBuilder = fetchBuilderResolverStack
|
||||
final FetchBuilder explicitFetchBuilder = (FetchBuilder) fetchBuilderResolverStack
|
||||
.getCurrent()
|
||||
.apply( fullPath );
|
||||
DynamicFetchBuilderLegacy fetchBuilderLegacy;
|
||||
|
@ -444,7 +444,7 @@ public class DomainResultCreationStateImpl
|
|||
}
|
||||
// todo (6.0): figure out if we can somehow create the navigable paths in a better way
|
||||
final String fullPath = currentEntry.getKey();
|
||||
FetchBuilder explicitFetchBuilder = fetchBuilderResolverStack
|
||||
FetchBuilder explicitFetchBuilder = (FetchBuilder) fetchBuilderResolverStack
|
||||
.getCurrent()
|
||||
.apply( fullPath );
|
||||
DynamicFetchBuilderLegacy fetchBuilderLegacy;
|
||||
|
@ -473,7 +473,7 @@ public class DomainResultCreationStateImpl
|
|||
currentEntry.getKey() + "." + partName,
|
||||
currentEntry.getValue().append( partName )
|
||||
);
|
||||
explicitFetchBuilder = fetchBuilderResolverStack
|
||||
explicitFetchBuilder = (FetchBuilder) fetchBuilderResolverStack
|
||||
.getCurrent()
|
||||
.apply( currentEntry.getKey() );
|
||||
if ( explicitFetchBuilder == null ) {
|
||||
|
|
|
@ -468,8 +468,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
private List<Map.Entry<OrderByFragment, TableGroup>> orderByFragments;
|
||||
|
||||
private final SqlAliasBaseManager sqlAliasBaseManager = new SqlAliasBaseManager();
|
||||
private final Stack<SqlAstProcessingState> processingStateStack = new StandardStack<>();
|
||||
private final Stack<FromClauseIndex> fromClauseIndexStack = new StandardStack<>();
|
||||
private final Stack<SqlAstProcessingState> processingStateStack = new StandardStack<>( SqlAstProcessingState.class );
|
||||
private final Stack<FromClauseIndex> fromClauseIndexStack = new StandardStack<>( FromClauseIndex.class );
|
||||
/*
|
||||
* Captures all entity names as which a table group was treated.
|
||||
* This information is used to prune tables from the table group.
|
||||
|
@ -486,11 +486,9 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
private SqmJoin<?, ?> currentlyProcessingJoin;
|
||||
protected Predicate additionalRestrictions;
|
||||
|
||||
private final Stack<Clause> currentClauseStack = new StandardStack<>();
|
||||
private final Stack<Supplier<MappingModelExpressible<?>>> inferrableTypeAccessStack = new StandardStack<>(
|
||||
() -> null
|
||||
);
|
||||
private final Stack<List<QueryTransformer>> queryTransformers = new StandardStack<>();
|
||||
private final Stack<Clause> currentClauseStack = new StandardStack<>( Clause.class );
|
||||
private final Stack<Supplier> inferrableTypeAccessStack = new StandardStack<>( Supplier.class );
|
||||
private final Stack<List> queryTransformers = new StandardStack<>( List.class );
|
||||
private boolean inTypeInference;
|
||||
private boolean inImpliedResultTypeInference;
|
||||
private Supplier<MappingModelExpressible<?>> functionImpliedResultTypeAccess;
|
||||
|
@ -513,6 +511,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
boolean deduplicateSelectionItems) {
|
||||
super( creationContext.getServiceRegistry() );
|
||||
|
||||
this.inferrableTypeAccessStack.push( () -> null );
|
||||
this.creationContext = creationContext;
|
||||
this.jpaQueryComplianceEnabled = creationContext
|
||||
.getSessionFactory()
|
||||
|
@ -2074,7 +2073,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
|
||||
QuerySpec finalQuerySpec = sqlQuerySpec;
|
||||
for ( QueryTransformer transformer : queryTransformers.getCurrent() ) {
|
||||
for ( QueryTransformer transformer : (List<QueryTransformer>) queryTransformers.getCurrent() ) {
|
||||
finalQuerySpec = transformer.transform(
|
||||
cteContainer,
|
||||
finalQuerySpec,
|
||||
|
|
|
@ -269,9 +269,9 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
|
||||
private final Set<FilterJdbcParameter> filterJdbcParameters = new HashSet<>();
|
||||
|
||||
private final Stack<Clause> clauseStack = new StandardStack<>();
|
||||
private final Stack<QueryPart> queryPartStack = new StandardStack<>();
|
||||
private final Stack<Statement> statementStack = new StandardStack<>();
|
||||
private final Stack<Clause> clauseStack = new StandardStack<>( Clause.class );
|
||||
private final Stack<QueryPart> queryPartStack = new StandardStack<>( QueryPart.class );
|
||||
private final Stack<Statement> statementStack = new StandardStack<>( Statement.class );
|
||||
|
||||
private final Dialect dialect;
|
||||
private final Set<String> affectedTableNames = new HashSet<>();
|
||||
|
|
|
@ -50,7 +50,7 @@ public class DomainResultGraphPrinter {
|
|||
}
|
||||
|
||||
private final StringBuilder buffer;
|
||||
private final Stack<FetchParent> fetchParentStack = new StandardStack<>();
|
||||
private final Stack<FetchParent> fetchParentStack = new StandardStack<>( FetchParent.class );
|
||||
|
||||
private DomainResultGraphPrinter(String header) {
|
||||
buffer = new StringBuilder( header + ":" + System.lineSeparator() );
|
||||
|
|
|
@ -31,7 +31,7 @@ public class LoadContexts {
|
|||
private static final CoreMessageLogger log = CoreLogging.messageLogger( LoadContexts.class );
|
||||
|
||||
private final PersistenceContext persistenceContext;
|
||||
private final StandardStack<JdbcValuesSourceProcessingState> jdbcValuesSourceProcessingStateStack = new StandardStack<>();
|
||||
private final StandardStack<JdbcValuesSourceProcessingState> jdbcValuesSourceProcessingStateStack = new StandardStack<>( JdbcValuesSourceProcessingState.class );
|
||||
|
||||
public LoadContexts(PersistenceContext persistenceContext) {
|
||||
this.persistenceContext = persistenceContext;
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.util;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.hibernate.internal.util.collections.Stack;
|
||||
import org.hibernate.internal.util.collections.StandardStack;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Marco Belladelli
|
||||
*/
|
||||
public class StandardStackTest {
|
||||
@Test
|
||||
public void testSimpleStackAccess() {
|
||||
final Stack<Integer> stack = allocateStack( 5 );
|
||||
assertEquals( 5, stack.depth() );
|
||||
assertEquals( 0, stack.getRoot() );
|
||||
assertEquals( 4, stack.getCurrent() );
|
||||
assertEquals( 4, stack.pop() );
|
||||
assertEquals( 4, stack.depth() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullValues() {
|
||||
final Stack<Integer> stack = allocateStack( 1 );
|
||||
stack.push( null );
|
||||
assertNull( stack.getCurrent() );
|
||||
assertNull( stack.pop() );
|
||||
assertNotNull( stack.getCurrent() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVisitRootFirst() {
|
||||
final Stack<Integer> stack = allocateStack( 5 );
|
||||
final int[] i = { 0 };
|
||||
stack.visitRootFirst( value -> {
|
||||
assertEquals( i[0], value );
|
||||
i[0]++;
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindCurrentFirst() {
|
||||
final Stack<Integer> stack = allocateStack( 5 );
|
||||
final Integer result = stack.findCurrentFirst( value -> value == 1 ? value : null );
|
||||
assertEquals( 1, result );
|
||||
final Integer nullResult = stack.findCurrentFirst( value -> value == 42 ? value : null );
|
||||
assertNull( nullResult );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindCurrentFirstWithParameter() {
|
||||
final Stack<Integer> stack = allocateStack( 5 );
|
||||
final Integer result = stack.findCurrentFirstWithParameter( 1, this::returnIfEquals );
|
||||
assertEquals( 1, result );
|
||||
final Integer nullResult = stack.findCurrentFirstWithParameter( 42, this::returnIfEquals );
|
||||
assertNull( nullResult );
|
||||
}
|
||||
|
||||
// empty stack tests
|
||||
|
||||
@Test
|
||||
public void testEmptyStackAccess() {
|
||||
final Stack<Integer> emptyStack = allocateStack( 0 );
|
||||
assertTrue( emptyStack.isEmpty() );
|
||||
assertNull( emptyStack.getRoot() );
|
||||
assertNull( emptyStack.getCurrent() );
|
||||
assertEquals( 0, emptyStack.depth() );
|
||||
assertThrows( NoSuchElementException.class, emptyStack::pop );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVisitRootFirstEmpty() {
|
||||
final Stack<Integer> emptyStack = allocateStack( 0 );
|
||||
final int[] i = { 0 };
|
||||
emptyStack.visitRootFirst( value -> i[0]++ );
|
||||
assertEquals( 0, i[0] ); // lambda function should never have been invoked
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindCurrentFirstEmpty() {
|
||||
final Stack<Integer> emptyStack = allocateStack( 0 );
|
||||
final Integer result = emptyStack.findCurrentFirst( value -> value );
|
||||
assertNull( result );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindCurrentFirstWithParameterEmpty() {
|
||||
final Stack<Integer> emptyStack = allocateStack( 0 );
|
||||
final Integer result = emptyStack.findCurrentFirstWithParameter( 1, (value, param) -> value );
|
||||
assertNull( result );
|
||||
}
|
||||
|
||||
// cleared stack tests
|
||||
|
||||
@Test
|
||||
public void testClear() {
|
||||
final Stack<Integer> clearedStack = allocateStack( 42 );
|
||||
assertEquals( 42, clearedStack.depth() );
|
||||
assertFalse( clearedStack.isEmpty() );
|
||||
clearedStack.clear();
|
||||
assertTrue( clearedStack.isEmpty() );
|
||||
assertNull( clearedStack.getRoot() );
|
||||
assertNull( clearedStack.getCurrent() );
|
||||
assertEquals( 0, clearedStack.depth() );
|
||||
assertThrows( NoSuchElementException.class, clearedStack::pop );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVisitRootFirstCleared() {
|
||||
final Stack<Integer> clearedStack = allocateStack( 5 );
|
||||
clearedStack.clear();
|
||||
final int[] i = { 0 };
|
||||
clearedStack.visitRootFirst( value -> i[0]++ );
|
||||
assertEquals( 0, i[0] ); // lambda function should never have been run
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindCurrentFirstCleared() {
|
||||
final Stack<Integer> clearedStack = allocateStack( 5 );
|
||||
clearedStack.clear();
|
||||
final Integer result = clearedStack.findCurrentFirst( value -> value );
|
||||
assertNull( result );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindCurrentFirstWithParameterCleared() {
|
||||
final Stack<Integer> clearedStack = allocateStack( 5 );
|
||||
clearedStack.clear();
|
||||
final Integer result = clearedStack.findCurrentFirstWithParameter( 1, (value, param) -> value );
|
||||
assertNull( result );
|
||||
}
|
||||
|
||||
// utility functions
|
||||
|
||||
private Stack<Integer> allocateStack(int size) {
|
||||
final Stack<Integer> stack = new StandardStack<>( Integer.class );
|
||||
for ( int i = 0; i < size; i++ ) {
|
||||
stack.push( i );
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
private Integer returnIfEquals(Integer value, Integer param) {
|
||||
return value.equals( param ) ? value : null;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue