StreamToLoop: support Optional unwrap if possible

This commit is contained in:
Tagir Valeev
2016-12-09 15:17:26 +07:00
parent ae273b6c24
commit 8e128b7f32
27 changed files with 425 additions and 90 deletions
@@ -0,0 +1,141 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInspection.streamToLoop;
import com.intellij.codeInspection.util.OptionalUtil;
import com.intellij.psi.util.TypeConversionUtil;
/**
* An interface representing the conditional expression to be generated in the resulting code
*
* @author Tagir Valeev
*/
interface Condition {
String getType();
String getCondition();
String getTrueBranch();
String getFalseBranch();
default String asExpression() {
return getCondition() + "?" + getTrueBranch() + ":" + getFalseBranch();
}
class Plain implements Condition {
private final String myType;
private final String myCondition;
private final String myTrueBranch;
private final String myFalseBranch;
public Plain(String type, String condition, String trueBranch, String falseBranch) {
myType = type;
myCondition = condition;
myTrueBranch = trueBranch;
myFalseBranch = falseBranch;
}
public String getType() {
return myType;
}
public String getCondition() {
return myCondition;
}
public String getTrueBranch() {
return myTrueBranch;
}
public String getFalseBranch() {
return myFalseBranch;
}
}
class Boolean implements Condition {
private String myCondition;
private boolean myInvert;
public Boolean(String condition, boolean invert) {
myCondition = condition;
myInvert = invert;
}
@Override
public String getType() {
return "boolean";
}
@Override
public String getCondition() {
return myCondition;
}
@Override
public String getTrueBranch() {
return String.valueOf(!myInvert);
}
@Override
public String getFalseBranch() {
return String.valueOf(myInvert);
}
@Override
public String asExpression() {
return myInvert ? myCondition : "!("+myCondition+")";
}
}
class Optional implements Condition {
private final String myType;
private final String myCondition;
private final String myPresentExpression;
private final String myTypeArgument;
Optional(String type, String condition, String presentExpression) {
myType = type;
myCondition = condition;
myPresentExpression = presentExpression;
myTypeArgument = TypeConversionUtil.isPrimitive(type) ? "" : "<" + type + ">";
}
@Override
public String getType() {
return OptionalUtil.getOptionalClass(myType) + myTypeArgument;
}
@Override
public String getCondition() {
return myCondition;
}
@Override
public String getTrueBranch() {
return OptionalUtil.getOptionalClass(myType) + "." + myTypeArgument + "of(" + myPresentExpression + ")";
}
@Override
public String getFalseBranch() {
return OptionalUtil.getOptionalClass(myType) + "." + myTypeArgument + "empty()";
}
public Plain unwrap(String absentExpression) {
return new Plain(myType, myCondition, myPresentExpression, absentExpression);
}
}
}
@@ -19,7 +19,6 @@ import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.util.OptionalUtil;
import com.intellij.lang.java.lexer.JavaLexer;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -31,8 +30,12 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.PsiDiamondTypeUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.util.RefactoringUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.StreamApiUtil;
import one.util.streamex.IntStreamEx;
@@ -43,6 +46,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.Predicate;
import static com.intellij.codeInspection.streamToLoop.Operation.FlatMapOperation;
@@ -223,7 +227,8 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
if(!(element instanceof PsiMethodCallExpression)) return;
PsiMethodCallExpression terminalCall = (PsiMethodCallExpression)element;
if(!isSupportedCodeLocation(terminalCall)) return;
boolean inReturn = terminalCall.getParent() instanceof PsiReturnStatement;
PsiType resultType = terminalCall.getType();
if (resultType == null) return;
List<OperationRecord> operations = extractOperations(StreamVariable.STUB, terminalCall);
TerminalOperation terminal = getTerminal(operations);
if (terminal == null) return;
@@ -233,9 +238,12 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
if(terminalCall == null) return;
PsiStatement statement = PsiTreeUtil.getParentOfType(terminalCall, PsiStatement.class);
LOG.assertTrue(statement != null);
PsiElement temporaryStreamPlaceholder = terminalCall.replace(factory.createExpressionFromText("$streamReplacement$", terminalCall));
PsiExpression temporaryStreamPlaceholder =
(PsiExpression)terminalCall
.replace(factory.createExpressionFromText("((" + resultType.getCanonicalText() + ")$streamReplacement$)", terminalCall));
try {
StreamToLoopReplacementContext context = new StreamToLoopReplacementContext(statement, operations, inReturn);
StreamToLoopReplacementContext context =
new StreamToLoopReplacementContext(statement, operations, temporaryStreamPlaceholder);
registerVariables(operations, context);
String replacement = "";
for (OperationRecord or : StreamEx.ofReversed(operations)) {
@@ -248,17 +256,10 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
.getCodeBlock().getStatements()) {
addStatement(project, statement, addedStatement);
}
String finisher = context.getFinisher();
if (finisher == null) {
temporaryStreamPlaceholder.delete();
}
else {
PsiExpression expression = factory.createExpressionFromText(finisher, temporaryStreamPlaceholder);
PsiElement parent = temporaryStreamPlaceholder.getParent();
if (parent instanceof PsiExpression && ParenthesesUtils.areParenthesesNeeded(expression, (PsiExpression)parent, false)) {
expression = factory.createExpressionFromText("("+expression.getText()+")", temporaryStreamPlaceholder);
}
normalize(project, temporaryStreamPlaceholder.replace(expression));
PsiElement result = context.makeFinalReplacement();
if(result != null) {
normalize(project, result);
}
}
catch (Exception ex) {
@@ -319,19 +320,21 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
static class StreamToLoopReplacementContext {
private final boolean myHasNestedLoops;
private final boolean myInReturn;
private final String mySuffix;
private final PsiStatement myStatement;
private final Set<String> myUsedNames;
private final Set<String> myUsedLabels;
private final List<String> myDeclarations = new ArrayList<>();
private PsiExpression myPlaceholder;
private final PsiElementFactory myFactory;
private String myLabel;
private String myFinisher;
StreamToLoopReplacementContext(PsiStatement statement, List<OperationRecord> records, boolean inReturn) {
StreamToLoopReplacementContext(PsiStatement statement, List<OperationRecord> records, @NotNull PsiExpression placeholder) {
myStatement = statement;
myFactory = JavaPsiFacade.getElementFactory(myStatement.getProject());
myHasNestedLoops = records.stream().anyMatch(or -> or.myOperation instanceof FlatMapOperation);
myInReturn = inReturn;
myPlaceholder = placeholder;
mySuffix = myHasNestedLoops ? "Outer" : "";
myUsedNames = new HashSet<>();
myUsedLabels = StreamEx.iterate(statement, Objects::nonNull, PsiElement::getParent).select(PsiLabeledStatement.class)
@@ -341,8 +344,9 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
StreamToLoopReplacementContext(StreamToLoopReplacementContext parentContext, List<OperationRecord> records) {
myUsedNames = parentContext.myUsedNames;
myUsedLabels = parentContext.myUsedLabels;
myInReturn = false;
myPlaceholder = null;
myStatement = parentContext.myStatement;
myFactory = parentContext.myFactory;
myHasNestedLoops = records.stream().anyMatch(or -> or.myOperation instanceof FlatMapOperation);
mySuffix = "Inner";
}
@@ -403,15 +407,6 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
return name;
}
public String assignAndBreak(String desiredName, String type, String foundValue, String notFoundValue) {
if(myInReturn) {
setFinisher(notFoundValue);
return "return "+foundValue+";";
}
String found = declareResult(desiredName, type, notFoundValue);
return found + " = " +foundValue+";\n" + getBreakStatement();
}
public void addInitStep(String initStatement) {
myDeclarations.add(initStatement);
}
@@ -426,18 +421,71 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
return name;
}
public String getFinisher() {
return myFinisher;
public PsiElement makeFinalReplacement() {
LOG.assertTrue(myPlaceholder != null);
if (myFinisher == null) {
myPlaceholder.delete();
return null;
}
else {
PsiExpression expression = myFactory.createExpressionFromText(myFinisher, myPlaceholder);
PsiElement parent = myPlaceholder.getParent();
if (parent instanceof PsiExpression && ParenthesesUtils.areParenthesesNeeded(expression, (PsiExpression)parent, false)) {
expression = myFactory.createExpressionFromText("("+myFinisher+")", myPlaceholder);
}
return myPlaceholder.replace(expression);
}
}
public void setFinisher(String finisher) {
myFinisher = finisher;
}
public void setOptionalUnwrapperFinisher(String seenVariable, String accVariable, String type) {
String optionalClass = OptionalUtil.getOptionalClass(type);
setFinisher(seenVariable + "?" + optionalClass + ".of(" + accVariable + "):" + optionalClass +
"." + (TypeConversionUtil.isPrimitive(type) ? "" : "<" + type + ">") + "empty()");
public String assignAndBreak(Condition condition) {
Predicate<PsiExpression> predicate = expr -> PsiUtil.skipParenthesizedExprUp(expr.getParent()) instanceof PsiReturnStatement;
if(condition instanceof Condition.Optional) {
condition = tryUnwrapOptional((Condition.Optional)condition, predicate);
}
if(predicate.test(myPlaceholder)) {
setFinisher(condition.getFalseBranch());
return "return "+condition.getTrueBranch()+";";
}
String found = declareResult(condition.getCondition(), condition.getType(), condition.getFalseBranch());
return found + " = " +condition.getTrueBranch()+";\n" + getBreakStatement();
}
@NotNull
private Condition tryUnwrapOptional(Condition.Optional condition, Predicate<PsiExpression> predicate) {
PsiMethodCallExpression call = ExpressionUtils.getCallForQualifier(myPlaceholder);
if(call != null && !(call.getParent() instanceof PsiExpressionStatement)) {
String name = call.getMethodExpression().getReferenceName();
PsiExpression[] args = call.getArgumentList().getExpressions();
if(args.length == 0 && "isPresent".equals(name)) {
myPlaceholder = call;
return new Condition.Boolean(condition.getCondition(), false);
}
if(args.length == 1) {
String absentExpression = null;
if("orElse".equals(name)) {
absentExpression = args[0].getText();
} else if("orElseGet".equals(name) && predicate.test(call)) {
FunctionHelper helper = FunctionHelper.create(args[0], 0);
if(helper != null) {
helper.transform(this);
absentExpression = helper.getText();
}
}
if(absentExpression != null) {
myPlaceholder = call;
return condition.unwrap(absentExpression);
}
}
}
return condition;
}
public void setOptionalUnwrapperFinisher(String seenCheck, String presentExpression, String type) {
setFinisher(tryUnwrapOptional(new Condition.Optional(type, seenCheck, presentExpression), expr -> true).asExpression());
}
public Project getProject() {
@@ -445,11 +493,11 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
}
public PsiExpression createExpression(String text) {
return JavaPsiFacade.getElementFactory(myStatement.getProject()).createExpressionFromText(text, myStatement);
return myFactory.createExpressionFromText(text, myStatement);
}
public PsiType createType(String text) {
return JavaPsiFacade.getElementFactory(myStatement.getProject()).createTypeFromText(text, myStatement);
return myFactory.createTypeFromText(text, myStatement);
}
}
@@ -86,7 +86,8 @@ abstract class TerminalOperation extends Operation {
return AccumulatedTerminalOperation.summarizing(resultType);
}
if((name.equals("findFirst") || name.equals("findAny")) && args.length == 0) {
return new FindTerminalOperation(resultType.getCanonicalText());
PsiType optionalElementType = OptionalUtil.getOptionalElementType(resultType);
return optionalElementType == null ? null : new FindTerminalOperation(optionalElementType.getCanonicalText());
}
if((name.equals("anyMatch") || name.equals("allMatch") || name.equals("noneMatch")) && args.length == 1) {
FunctionHelper fn = FunctionHelper.create(args[0], 1);
@@ -333,12 +334,14 @@ abstract class TerminalOperation extends Operation {
String accumulator = context.declareResult("acc", myType, TypeConversionUtil.isPrimitive(myType) ? "0" : "null");
myUpdater.transform(context, accumulator, inVar.getName());
context.setOptionalUnwrapperFinisher(seen, accumulator, myType);
return "if(!" + seen + ") {\n" +
seen + "=true;\n" +
accumulator + "=" + inVar + ";\n" +
"} else {\n" +
accumulator + "=" + myUpdater.getText() + ";\n" +
"}\n";
String ifClause = "if(!" + seen + ") {\n" +
seen + "=true;\n" +
accumulator + "=" + inVar + ";\n" +
"}";
if(myUpdater.getText().equals(accumulator)) {
return ifClause + "\n";
}
return ifClause + " else {\n" + accumulator + "=" + myUpdater.getText() + ";\n}\n";
}
@Nullable
@@ -395,12 +398,14 @@ abstract class TerminalOperation extends Operation {
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
String sum = context.declareResult("sum", myDoubleAccumulator ? "double" : "long", "0");
String count = context.declare("count", "long", "0");
String emptyCheck = count + "==0";
String seenCheck = count + ">0";
String result = (myDoubleAccumulator ? "" : "(double)") + sum + "/" + count;
context.setFinisher(myUseOptional
? emptyCheck + "?java.util.OptionalDouble.empty():"
+ "java.util.OptionalDouble.of(" + result + ")"
: emptyCheck + "?0.0:" + result);
if (myUseOptional) {
context.setOptionalUnwrapperFinisher(seenCheck, result, "double");
}
else {
context.setFinisher(seenCheck + "?" + result + ":0.0");
}
return sum + "+=" + inVar + ";\n" + count + "++;\n";
}
}
@@ -431,9 +436,7 @@ abstract class TerminalOperation extends Operation {
@Override
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
int pos = myType.indexOf('<');
String optType = pos == -1 ? myType : myType.substring(0, pos);
return context.assignAndBreak("found", myType, optType + ".of(" + inVar + ")", optType + ".empty()");
return context.assignAndBreak(new Condition.Optional(myType, "found", inVar.getName()));
}
}
@@ -487,7 +490,7 @@ abstract class TerminalOperation extends Operation {
expression = myFn.getText();
}
return "if(" + expression + ") {\n" +
context.assignAndBreak(myName, PsiType.BOOLEAN.getCanonicalText(), String.valueOf(!myDefaultValue), String.valueOf(myDefaultValue)) +
context.assignAndBreak(new Condition.Boolean(myName, myDefaultValue)) +
"}\n";
}
}
@@ -14,7 +14,7 @@ public class Main {
count++;
}
}
return count == 0 ? OptionalDouble.empty() : OptionalDouble.of(sum / count);
return count > 0 ? OptionalDouble.of(sum / count) : OptionalDouble.empty();
}
public static void main(String[] args) {
@@ -13,7 +13,7 @@ public class Main {
count++;
}
}
return count == 0 ? OptionalDouble.empty() : OptionalDouble.of((double) sum / count);
return count > 0 ? OptionalDouble.of((double) sum / count) : OptionalDouble.empty();
}
public static void main(String[] args) {
@@ -13,7 +13,7 @@ public class Main {
count++;
}
}
return count == 0 ? OptionalDouble.empty() : OptionalDouble.of((double) sum / count);
return count > 0 ? OptionalDouble.of((double) sum / count) : OptionalDouble.empty();
}
public static void main(String[] args) {
@@ -14,7 +14,7 @@ public class Main {
count++;
}
}
System.out.println(count == 0 ? 0.0 : sum / count);
System.out.println(count > 0 ? sum / count : 0.0);
}
public static void main(String[] args) {
@@ -14,7 +14,7 @@ public class Main {
count++;
}
}
System.out.println(count == 0 ? 0.0 : (double) sum / count);
System.out.println(count > 0 ? (double) sum / count : 0.0);
}
public static void main(String[] args) {
@@ -7,21 +7,22 @@ import static java.util.Arrays.asList;
public class Main {
public static Optional<String> test(List<List<String>> list) {
String res = null;
OUTER:
for(int i=0; i<10; i++) {
Optional<String> found = Optional.empty();
String found = "";
OUTER1:
for (List<String> x : list) {
if (x != null) {
for (String s : x) {
found = Optional.of(s);
found = s;
break OUTER1;
}
}
}
return found.orElse("");
res = found;
}
return null;
return res;
}
public static void main(String[] args) {
@@ -0,0 +1,22 @@
// "Replace Stream API chain with loop" "true"
import java.util.*;
import static java.util.Arrays.asList;
public class Main {
public static boolean test(List<List<String>> list) {
for (List<String> strings : list) {
if (Objects.nonNull(strings)) {
for (String s : strings) {
return true;
}
}
}
return false;
}
public static void main(String[] args) {
System.out.println(test(asList(asList(), asList("a"), asList("b", "c"))));
}
}
@@ -6,14 +6,12 @@ import java.util.stream.*;
public class Main {
private static int test() {
OptionalInt found = OptionalInt.empty();
for (int x = 0; x < 100; x++) {
if (x > 50) {
found = OptionalInt.of(x);
break;
return x;
}
}
return found.orElse(0);
return 0;
}
public static void main(String[] args) {
@@ -0,0 +1,20 @@
// "Replace Stream API chain with loop" "true"
import java.util.*;
import java.util.stream.*;
public class Main {
private static int test() {
for (int x = 0; x < 100; x++) {
if (x > 50) {
return x;
}
}
return Math.abs(-1);
}
public static void main(String[] args) {
System.out.println(test());
}
}
@@ -0,0 +1,23 @@
// "Replace Stream API chain with loop" "true"
import java.util.*;
import java.util.stream.*;
public class Main {
private static int test() {
OptionalInt found = OptionalInt.empty();
for (int x = 0; x < 100; x++) {
if (x > 50) {
found = OptionalInt.of(x);
break;
}
}
int res = found.orElseGet(() -> Math.abs(-1));
return res;
}
public static void main(String[] args) {
System.out.println(test());
}
}
@@ -16,7 +16,7 @@ public class Main {
count++;
}
}
return count == 0 ? 0.0 : (double) sum / count;
return count > 0 ? (double) sum / count : 0.0;
};
System.out.println(s.getAsDouble());
}
@@ -3,7 +3,6 @@
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
public class Main {
public static String test(List<String> strings) {
@@ -16,7 +15,7 @@ public class Main {
best = string;
}
}
return (seen ? Optional.of(best) : Optional.<String>empty()).orElse(null);
return seen ? best : null;
}
public static void main(String[] args) {
@@ -3,7 +3,6 @@
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
public class Main {
public static String test(List<String> strings, Comparator<String> cmp) {
@@ -15,7 +14,7 @@ public class Main {
best = string;
}
}
return (seen ? Optional.of(best) : Optional.<String>empty()).orElse(null);
return seen ? best : null;
}
public static void main(String[] args) {
@@ -3,7 +3,6 @@
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
public class Main {
public static String test(List<String> strings, Comparator<CharSequence> comparator) {
@@ -16,7 +15,7 @@ public class Main {
best = string;
}
}
return (seen ? Optional.of(best) : Optional.<String>empty()).orElse(null);
return seen ? best : strings.toString();
}
public static void main(String[] args) {
@@ -2,10 +2,10 @@
import java.util.Arrays;
import java.util.List;
import java.util.OptionalInt;
import java.util.function.IntSupplier;
public class Main {
public static int test(List<String> strings) {
public static int test(List<String> strings, IntSupplier supplier) {
boolean seen = false;
int best = 0;
for (String string : strings) {
@@ -15,11 +15,11 @@ public class Main {
best = length;
}
}
return (seen ? OptionalInt.of(best) : OptionalInt.empty()).orElse(-1);
return seen ? best : supplier.getAsInt();
}
public static void main(String[] args) {
System.out.println(test(Arrays.asList()));
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d")));
System.out.println(test(Arrays.asList(), () -> -1));
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d"), () -> 2));
}
}
@@ -2,20 +2,17 @@
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class Main {
private static String test(List<String> list) {
if (list == null) return null;
else {
Optional<String> found = Optional.empty();
for (String str : list) {
if (str.contains("x")) {
found = Optional.of(str);
break;
return str;
}
}
return found.orElse(null);
return null;
}
}
@@ -0,0 +1,22 @@
// "Replace Stream API chain with loop" "true"
import java.util.Arrays;
import java.util.List;
public class Main {
private static String test(List<String> list) {
if (list == null) return null;
else {
for (String str : list) {
if (str.contains("x")) {
return str;
}
}
return null;
}
}
public static void main(String[] args) {
System.out.println(test(Arrays.asList("a", "b", "syz")));
}
}
@@ -7,11 +7,12 @@ import static java.util.Arrays.asList;
public class Main {
public static Optional<String> test(List<List<String>> list) {
String res = null;
OUTER:
for(int i=0; i<10; i++) {
return list.stream().filter(x -> x != null).flatMap(x -> x.stream()).fi<caret>ndAny().orElse("");
res = list.stream().filter(x -> x != null).flatMap(x -> x.stream()).fi<caret>ndAny().orElse("");
}
return null;
return res;
}
public static void main(String[] args) {
@@ -0,0 +1,15 @@
// "Replace Stream API chain with loop" "true"
import java.util.*;
import static java.util.Arrays.asList;
public class Main {
public static boolean test(List<List<String>> list) {
return list.stream().filter(Objects::nonNull).flatMap(List::stream).findA<caret>ny().isPresent();
}
public static void main(String[] args) {
System.out.println(test(asList(asList(), asList("a"), asList("b", "c"))));
}
}
@@ -0,0 +1,15 @@
// "Replace Stream API chain with loop" "true"
import java.util.*;
import java.util.stream.*;
public class Main {
private static int test() {
return IntStream.range(0, 100).filter(x -> x > 50).findFir<caret>st().orElseGet(() -> Math.abs(-1));
}
public static void main(String[] args) {
System.out.println(test());
}
}
@@ -0,0 +1,16 @@
// "Replace Stream API chain with loop" "true"
import java.util.*;
import java.util.stream.*;
public class Main {
private static int test() {
int res = IntStream.range(0, 100).filter(x -> x > 50).findFir<caret>st().orElseGet(() -> Math.abs(-1));
return res;
}
public static void main(String[] args) {
System.out.println(test());
}
}
@@ -6,7 +6,7 @@ import java.util.List;
public class Main {
public static String test(List<String> strings, Comparator<CharSequence> comparator) {
return strings.stream().m<caret>in(comparator.reversed()).orElse(null);
return strings.stream().m<caret>in(comparator.reversed()).orElseGet(strings::toString);
}
public static void main(String[] args) {
@@ -2,14 +2,15 @@
import java.util.Arrays;
import java.util.List;
import java.util.function.IntSupplier;
public class Main {
public static int test(List<String> strings) {
return strings.stream().mapToInt(String::length).mi<caret>n().orElse(-1);
public static int test(List<String> strings, IntSupplier supplier) {
return strings.stream().mapToInt(String::length).mi<caret>n().orElseGet(supplier);
}
public static void main(String[] args) {
System.out.println(test(Arrays.asList()));
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d")));
System.out.println(test(Arrays.asList(), () -> -1));
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d"), () -> 2));
}
}
@@ -0,0 +1,15 @@
// "Replace Stream API chain with loop" "true"
import java.util.Arrays;
import java.util.List;
public class Main {
private static String test(List<String> list) {
if (list == null) return null;
else return list.stream().filter(str -> str.contains("x")).fin<caret>dFirst().orElseGet(() -> null);
}
public static void main(String[] args) {
System.out.println(test(Arrays.asList("a", "b", "syz")));
}
}