mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
IDEA-163405 Migration from Stream API back to for loops: iteration#2
This commit is contained in:
@@ -17,6 +17,7 @@ package com.intellij.codeInspection.streamToLoop;
|
||||
|
||||
import com.intellij.codeInspection.streamToLoop.StreamToLoopInspection.StreamToLoopReplacementContext;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo;
|
||||
@@ -24,14 +25,16 @@ import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.refactoring.util.LambdaRefactoringUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ig.psiutils.MethodCallUtils;
|
||||
import one.util.streamex.EntryStream;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.OptionalLong;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -42,6 +45,16 @@ import java.util.function.Consumer;
|
||||
abstract class FunctionHelper {
|
||||
private static final Logger LOG = Logger.getInstance(FunctionHelper.class);
|
||||
|
||||
private String myResultType;
|
||||
|
||||
FunctionHelper(PsiType resultType) {
|
||||
myResultType = resultType.getCanonicalText();
|
||||
}
|
||||
|
||||
String getResultType() {
|
||||
return myResultType;
|
||||
}
|
||||
|
||||
String getText() {
|
||||
return getExpression().getText();
|
||||
}
|
||||
@@ -55,7 +68,9 @@ abstract class FunctionHelper {
|
||||
* @return SAM argument name or null if function helper refused to perform a transformation.
|
||||
* @param type
|
||||
*/
|
||||
abstract String tryLightTransform(PsiType type);
|
||||
String tryLightTransform(PsiType type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an adaptation of current function helper to the replacement context with given parameter names.
|
||||
@@ -73,12 +88,14 @@ abstract class FunctionHelper {
|
||||
* @param newName new variable name
|
||||
* @param context a context
|
||||
*/
|
||||
abstract void rename(String oldName, String newName, StreamToLoopReplacementContext context);
|
||||
void rename(String oldName, String newName, StreamToLoopReplacementContext context) {}
|
||||
|
||||
abstract void registerUsedNames(Consumer<String> consumer);
|
||||
void registerUsedNames(Consumer<String> consumer) {}
|
||||
|
||||
@Nullable
|
||||
abstract String getParameterName(int index);
|
||||
String getParameterName(int index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
void suggestVariableName(StreamVariable var, int index) {
|
||||
String name = getParameterName(index);
|
||||
@@ -87,36 +104,72 @@ abstract class FunctionHelper {
|
||||
}
|
||||
}
|
||||
|
||||
void suggestOutputNames(StreamVariable var) {}
|
||||
|
||||
List<String> suggestFinalOutputNames(StreamToLoopReplacementContext context, String desiredName, String worstCaseName) {
|
||||
List<String> candidates = Arrays.asList(JavaCodeStyleManager.getInstance(context.getProject())
|
||||
.suggestVariableName(VariableKind.LOCAL_VARIABLE, desiredName,
|
||||
context.createExpression(getText()),
|
||||
context.createType(getResultType())).names);
|
||||
if(candidates.isEmpty() && worstCaseName != null) candidates = Collections.singletonList(worstCaseName);
|
||||
return candidates;
|
||||
}
|
||||
|
||||
@Contract("null, _ -> null")
|
||||
@Nullable
|
||||
static FunctionHelper create(PsiExpression expression, int paramCount) {
|
||||
if(expression == null) return null;
|
||||
PsiType type = expression instanceof PsiFunctionalExpression
|
||||
? ((PsiFunctionalExpression)expression).getFunctionalInterfaceType()
|
||||
: expression.getType();
|
||||
if(!(type instanceof PsiClassType)) return null;
|
||||
PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(type);
|
||||
if (interfaceMethod == null || interfaceMethod.getParameterList().getParametersCount() != paramCount) return null;
|
||||
PsiType returnType = interfaceMethod.getReturnType();
|
||||
if (returnType == null) return null;
|
||||
returnType = ((PsiClassType)type).resolveGenerics().getSubstitutor().substitute(returnType);
|
||||
if (expression instanceof PsiLambdaExpression) {
|
||||
PsiLambdaExpression lambda = (PsiLambdaExpression)expression;
|
||||
PsiType functionalInterfaceType = lambda.getFunctionalInterfaceType();
|
||||
if(functionalInterfaceType == null) return null;
|
||||
PsiParameterList list = lambda.getParameterList();
|
||||
if (list.getParametersCount() != paramCount) return null;
|
||||
String[] parameters = StreamEx.of(list.getParameters()).map(PsiVariable::getName).toArray(String[]::new);
|
||||
PsiExpression body = LambdaUtil.extractSingleExpressionFromBody(lambda.getBody());
|
||||
if (body == null) return null;
|
||||
return new LambdaFunctionHelper(body, parameters);
|
||||
return new LambdaFunctionHelper(returnType, body, parameters);
|
||||
}
|
||||
if (expression instanceof PsiMethodReferenceExpression) {
|
||||
PsiMethodReferenceExpression methodRef = (PsiMethodReferenceExpression)expression;
|
||||
if (methodRef.resolve() == null) return null;
|
||||
PsiType functionalInterfaceType = methodRef.getFunctionalInterfaceType();
|
||||
PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType);
|
||||
if (interfaceMethod == null) return null;
|
||||
if (interfaceMethod.getParameterList().getParametersCount() != paramCount) return null;
|
||||
return new MethodReferenceFunctionHelper(functionalInterfaceType, methodRef);
|
||||
return new MethodReferenceFunctionHelper(returnType, type, methodRef);
|
||||
}
|
||||
if (expression instanceof PsiReferenceExpression && ExpressionUtils.isSimpleExpression(expression)) {
|
||||
PsiType functionalInterfaceType = expression.getType();
|
||||
PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType);
|
||||
if (interfaceMethod == null || interfaceMethod.getParameterList().getParametersCount() != paramCount) return null;
|
||||
return new SimpleReferenceFunctionHelper(expression, interfaceMethod.getName());
|
||||
return new SimpleReferenceFunctionHelper(returnType, expression, interfaceMethod.getName());
|
||||
}
|
||||
return null;
|
||||
if (expression instanceof PsiMethodCallExpression &&
|
||||
MethodCallUtils
|
||||
.isCallToStaticMethod((PsiMethodCallExpression)expression, CommonClassNames.JAVA_UTIL_FUNCTION_FUNCTION, "identity", 0)) {
|
||||
return paramCount == 1 ? new IdentityFunctionHelper(returnType) : null;
|
||||
}
|
||||
return new ComplexExpressionFunctionHelper(returnType, type, interfaceMethod.getName(), expression);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
static FunctionHelper hashMapSupplier(PsiType type) {
|
||||
return new FunctionHelper(type) {
|
||||
PsiExpression myExpression;
|
||||
|
||||
@Override
|
||||
PsiExpression getExpression() {
|
||||
return myExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
void transform(StreamToLoopReplacementContext context, String... newNames) {
|
||||
LOG.assertTrue(newNames.length == 0);
|
||||
myExpression = context.createExpression("new java.util.HashMap<>()");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,7 +218,8 @@ abstract class FunctionHelper {
|
||||
private PsiMethodReferenceExpression myMethodRef;
|
||||
private PsiExpression myExpression;
|
||||
|
||||
public MethodReferenceFunctionHelper(PsiType functionalInterfaceType, PsiMethodReferenceExpression methodRef) {
|
||||
public MethodReferenceFunctionHelper(PsiType returnType, PsiType functionalInterfaceType, PsiMethodReferenceExpression methodRef) {
|
||||
super(returnType);
|
||||
myMethodRef = methodRef;
|
||||
myType = functionalInterfaceType.getCanonicalText();
|
||||
PsiExpression qualifier = methodRef.getQualifierExpression();
|
||||
@@ -258,11 +312,61 @@ abstract class FunctionHelper {
|
||||
qualifier = renameVarReference(qualifier, oldName, newName, context);
|
||||
myMethodRef = fromText(context, qualifier.getText()+"::"+myMethodRef.getReferenceName());
|
||||
}
|
||||
}
|
||||
|
||||
private static class ComplexExpressionFunctionHelper extends FunctionHelper {
|
||||
private final String myMethodName;
|
||||
private final String myNameCandidate;
|
||||
private final String myFnType;
|
||||
private PsiExpression myExpression;
|
||||
private PsiExpression myFinalExpression;
|
||||
|
||||
private ComplexExpressionFunctionHelper(PsiType type, PsiType functionalInterface, String name, PsiExpression expression) {
|
||||
super(type);
|
||||
myMethodName = name;
|
||||
myExpression = expression;
|
||||
myNameCandidate = getNameCandidate(functionalInterface);
|
||||
myFnType = functionalInterface.getCanonicalText();
|
||||
}
|
||||
|
||||
private String getNameCandidate(PsiType functionalInterface) {
|
||||
PsiElement parent = myExpression.getParent();
|
||||
if(parent instanceof PsiExpressionList) {
|
||||
int idx = ArrayUtil.indexOf(((PsiExpressionList)parent).getExpressions(), myExpression);
|
||||
PsiElement gParent = parent.getParent();
|
||||
if(gParent instanceof PsiMethodCallExpression && idx >= 0) {
|
||||
PsiMethod method = ((PsiMethodCallExpression)gParent).resolveMethod();
|
||||
if(method != null) {
|
||||
PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if(idx < parameters.length) {
|
||||
return parameters[idx].getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return functionalInterface.getPresentableText().toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
String getParameterName(int index) {
|
||||
return null;
|
||||
PsiExpression getExpression() {
|
||||
LOG.assertTrue(myFinalExpression != null);
|
||||
return myFinalExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
void rename(String oldName, String newName, StreamToLoopReplacementContext context) {
|
||||
myExpression = renameVarReference(myExpression, oldName, newName, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> consumer) {
|
||||
processUsedNames(myExpression, consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
void transform(StreamToLoopReplacementContext context, String... newNames) {
|
||||
String varName = context.declare(myNameCandidate, myFnType, myExpression.getText());
|
||||
myFinalExpression = context.createExpression(varName + "." + myMethodName + "(" + String.join(",", newNames) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,16 +375,12 @@ abstract class FunctionHelper {
|
||||
private final String myName;
|
||||
private PsiExpression myExpression;
|
||||
|
||||
public SimpleReferenceFunctionHelper(PsiExpression reference, String methodName) {
|
||||
public SimpleReferenceFunctionHelper(PsiType returnType, PsiExpression reference, String methodName) {
|
||||
super(returnType);
|
||||
myReference = reference;
|
||||
myName = methodName;
|
||||
}
|
||||
|
||||
@Override
|
||||
String tryLightTransform(PsiType type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
PsiExpression getExpression() {
|
||||
LOG.assertTrue(myExpression != null);
|
||||
@@ -301,11 +401,25 @@ abstract class FunctionHelper {
|
||||
void registerUsedNames(Consumer<String> consumer) {
|
||||
processUsedNames(myReference, consumer);
|
||||
}
|
||||
}
|
||||
|
||||
private static class IdentityFunctionHelper extends FunctionHelper {
|
||||
private PsiExpression myExpression;
|
||||
|
||||
public IdentityFunctionHelper(PsiType type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
String getParameterName(int index) {
|
||||
return null;
|
||||
PsiExpression getExpression() {
|
||||
LOG.assertTrue(myExpression != null);
|
||||
return myExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
void transform(StreamToLoopReplacementContext context, String... newNames) {
|
||||
LOG.assertTrue(newNames.length == 1);
|
||||
myExpression = context.createExpression(newNames[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,7 +427,8 @@ abstract class FunctionHelper {
|
||||
private String[] myParameters;
|
||||
private PsiExpression myBody;
|
||||
|
||||
LambdaFunctionHelper(PsiExpression body, String[] parameters) {
|
||||
LambdaFunctionHelper(PsiType returnType, PsiExpression body, String[] parameters) {
|
||||
super(returnType);
|
||||
myParameters = parameters;
|
||||
myBody = body;
|
||||
}
|
||||
@@ -365,5 +480,17 @@ abstract class FunctionHelper {
|
||||
String getParameterName(int index) {
|
||||
return myParameters[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
void suggestOutputNames(StreamVariable var) {
|
||||
String text = "("+var.getType()+")"+getText();
|
||||
Project project = myBody.getProject();
|
||||
PsiExpression expr = JavaPsiFacade.getElementFactory(project).createExpressionFromText(text, myBody);
|
||||
SuggestedNameInfo info =
|
||||
JavaCodeStyleManager.getInstance(project).suggestVariableName(VariableKind.LOCAL_VARIABLE, null, expr, null, true);
|
||||
for (String name : info.names) {
|
||||
var.addOtherNameCandidate(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,10 +46,12 @@ abstract class Operation {
|
||||
String code,
|
||||
StreamToLoopReplacementContext context);
|
||||
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
|
||||
Operation combineWithNext(Operation next) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {}
|
||||
|
||||
public void suggestNames(StreamVariable inVar, StreamVariable outVar) {}
|
||||
|
||||
@Nullable
|
||||
@@ -98,7 +100,7 @@ abstract class Operation {
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
myFn.registerUsedNames(usedNameConsumer);
|
||||
}
|
||||
|
||||
@@ -148,6 +150,12 @@ abstract class Operation {
|
||||
super(fn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestNames(StreamVariable inVar, StreamVariable outVar) {
|
||||
super.suggestNames(inVar, outVar);
|
||||
myFn.suggestOutputNames(outVar);
|
||||
}
|
||||
|
||||
@Override
|
||||
String wrap(StreamVariable outVar, String code, StreamToLoopReplacementContext context) {
|
||||
return outVar.getDeclaration() + " = " + myFn.getText() + ";\n" + code;
|
||||
@@ -201,7 +209,7 @@ abstract class Operation {
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
myRecords.forEach(or -> or.myOperation.registerUsedNames(usedNameConsumer));
|
||||
}
|
||||
|
||||
@@ -260,7 +268,7 @@ abstract class Operation {
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
FunctionHelper.processUsedNames(myExpression, usedNameConsumer);
|
||||
}
|
||||
|
||||
@@ -272,25 +280,25 @@ abstract class Operation {
|
||||
}
|
||||
|
||||
static class LimitOperation extends Operation {
|
||||
PsiExpression myExpression;
|
||||
PsiExpression myLimit;
|
||||
|
||||
LimitOperation(PsiExpression expression) {
|
||||
myExpression = expression;
|
||||
myLimit = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
void rename(String oldName, String newName, StreamToLoopReplacementContext context) {
|
||||
myExpression = FunctionHelper.renameVarReference(myExpression, oldName, newName, context);
|
||||
myLimit = FunctionHelper.renameVarReference(myLimit, oldName, newName, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
FunctionHelper.processUsedNames(myExpression, usedNameConsumer);
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
FunctionHelper.processUsedNames(myLimit, usedNameConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
String wrap(StreamVariable inVar, StreamVariable outVar, String code, StreamToLoopReplacementContext context) {
|
||||
String limit = context.declare("limit", "long", myExpression.getText());
|
||||
String limit = context.declare("limit", "long", myLimit.getText());
|
||||
return "if(" + limit + "--==0) " + context.getBreakStatement() + code;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ abstract class SourceOperation extends Operation {
|
||||
if (name.equals("generate") && args.length == 1 && method.getModifierList().hasExplicitModifier(
|
||||
PsiModifier.STATIC) && className.startsWith("java.util.stream.")) {
|
||||
FunctionHelper fn = FunctionHelper.create(args[0], 0);
|
||||
return fn == null ? null : new GenerateSource(fn);
|
||||
return fn == null ? null : new GenerateSource(fn, null);
|
||||
}
|
||||
if (name.equals("iterate") && args.length == 2 && method.getModifierList().hasExplicitModifier(
|
||||
PsiModifier.STATIC) && className.startsWith("java.util.stream.")) {
|
||||
@@ -113,7 +113,7 @@ abstract class SourceOperation extends Operation {
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
processUsedNames(myQualifier, usedNameConsumer);
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ abstract class SourceOperation extends Operation {
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
for(PsiExpression arg : myArgList) {
|
||||
processUsedNames(arg, usedNameConsumer);
|
||||
}
|
||||
@@ -170,26 +170,47 @@ abstract class SourceOperation extends Operation {
|
||||
|
||||
static class GenerateSource extends SourceOperation {
|
||||
private FunctionHelper myFn;
|
||||
private PsiExpression myLimit;
|
||||
|
||||
GenerateSource(FunctionHelper fn) {
|
||||
GenerateSource(FunctionHelper fn, PsiExpression limit) {
|
||||
myFn = fn;
|
||||
myLimit = limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
Operation combineWithNext(Operation next) {
|
||||
if(myLimit == null && next instanceof LimitOperation) {
|
||||
return new GenerateSource(myFn, ((LimitOperation)next).myLimit);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
void rename(String oldName, String newName, StreamToLoopReplacementContext context) {
|
||||
myFn.rename(oldName, newName, context);
|
||||
if(myLimit != null) {
|
||||
myLimit = renameVarReference(myLimit, oldName, newName, context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
myFn.registerUsedNames(usedNameConsumer);
|
||||
if(myLimit != null) {
|
||||
processUsedNames(myLimit, usedNameConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
String wrap(StreamVariable outVar, String code, StreamToLoopReplacementContext context) {
|
||||
myFn.transform(context);
|
||||
String loop = "while(true)";
|
||||
if(myLimit != null) {
|
||||
String loopIdx = context.registerVarName(Arrays.asList("count", "limit"));
|
||||
loop = "for(long "+loopIdx+"="+myLimit.getText()+";"+loopIdx+">0;"+loopIdx+"--)";
|
||||
}
|
||||
return context.getLoopLabel() +
|
||||
"while(true) {\n" +
|
||||
loop+"{\n" +
|
||||
outVar.getDeclaration() + "=" + myFn.getText() + ";\n" + code +
|
||||
"}\n";
|
||||
}
|
||||
@@ -211,7 +232,7 @@ abstract class SourceOperation extends Operation {
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
processUsedNames(myInitializer, usedNameConsumer);
|
||||
myFn.registerUsedNames(usedNameConsumer);
|
||||
}
|
||||
@@ -248,7 +269,7 @@ abstract class SourceOperation extends Operation {
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
processUsedNames(myOrigin, usedNameConsumer);
|
||||
processUsedNames(myBound, usedNameConsumer);
|
||||
}
|
||||
|
||||
+34
-10
@@ -20,6 +20,7 @@ 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;
|
||||
@@ -27,11 +28,9 @@ import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
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.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.siyeh.ig.psiutils.StreamApiUtil;
|
||||
import one.util.streamex.IntStreamEx;
|
||||
import one.util.streamex.StreamEx;
|
||||
@@ -53,7 +52,7 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
// To quickly filter out most of the non-interesting method calls
|
||||
private static final Set<String> SUPPORTED_TERMINALS = StreamEx.of("count", "sum", "summaryStatistics", "reduce", "collect",
|
||||
"findFirst", "findAny", "anyMatch", "allMatch", "noneMatch",
|
||||
"toArray", "average", "forEach", "forEachOrdered").toSet();
|
||||
"toArray", "average", "forEach", "forEachOrdered", "min", "max").toSet();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -157,9 +156,17 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
List<OperationRecord> operations = new ArrayList<>();
|
||||
PsiMethodCallExpression currentCall = terminalCall;
|
||||
StreamVariable lastVar = outVar;
|
||||
Operation next = null;
|
||||
while(true) {
|
||||
Operation op = createOperationFromCall(lastVar, currentCall);
|
||||
if(op == null) return null;
|
||||
if(next != null) {
|
||||
Operation combined = op.combineWithNext(next);
|
||||
if (combined != null) {
|
||||
op = combined;
|
||||
operations.remove(operations.size() - 1);
|
||||
}
|
||||
}
|
||||
OperationRecord or = new OperationRecord();
|
||||
or.myOperation = op;
|
||||
or.myOutVar = lastVar;
|
||||
@@ -175,9 +182,10 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
if(op.changesVariable()) {
|
||||
PsiType type = StreamApiUtil.getStreamElementType(currentCall.getType());
|
||||
if(type == null) return null;
|
||||
lastVar = new StreamVariable(type);
|
||||
lastVar = new StreamVariable(type.getCanonicalText());
|
||||
}
|
||||
or.myInVar = lastVar;
|
||||
next = op;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +245,7 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
temporaryStreamPlaceholder.delete();
|
||||
}
|
||||
else {
|
||||
temporaryStreamPlaceholder.replace(factory.createExpressionFromText(finisher, temporaryStreamPlaceholder));
|
||||
normalize(project, temporaryStreamPlaceholder.replace(factory.createExpressionFromText(finisher, temporaryStreamPlaceholder)));
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
@@ -250,9 +258,15 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
}
|
||||
|
||||
void addStatement(@NotNull Project project, PsiStatement statement, PsiStatement context) {
|
||||
CodeStyleManager.getInstance(project)
|
||||
.reformat(JavaCodeStyleManager.getInstance(project).shortenClassReferences(statement.getParent().addBefore(context, statement)));
|
||||
private static void addStatement(@NotNull Project project, PsiStatement statement, PsiStatement context) {
|
||||
PsiElement element = statement.getParent().addBefore(context, statement);
|
||||
normalize(project, element);
|
||||
}
|
||||
|
||||
private static void normalize(@NotNull Project project, PsiElement element) {
|
||||
element = JavaCodeStyleManager.getInstance(project).shortenClassReferences(element);
|
||||
PsiDiamondTypeUtil.removeRedundantTypeArguments(element);
|
||||
CodeStyleManager.getInstance(project).reformat(element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -381,6 +395,10 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
return found + " = " +foundValue+";\n" + getBreakStatement();
|
||||
}
|
||||
|
||||
public void addInitStep(String initStatement) {
|
||||
myDeclarations.add(initStatement);
|
||||
}
|
||||
|
||||
public String declareResult(String desiredName, String type, String initializer) {
|
||||
String name = registerVarName(Arrays.asList(desiredName, "result"));
|
||||
myDeclarations.add(type + " " + name + " = " + initializer + ";");
|
||||
@@ -399,6 +417,12 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
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 Project getProject() {
|
||||
return myStatement.getProject();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package com.intellij.codeInspection.streamToLoop;
|
||||
|
||||
import com.intellij.codeInspection.streamToLoop.StreamToLoopInspection.StreamToLoopReplacementContext;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import one.util.streamex.StreamEx;
|
||||
@@ -39,7 +38,7 @@ import java.util.List;
|
||||
class StreamVariable {
|
||||
private static final Logger LOG = Logger.getInstance(StreamVariable.class);
|
||||
|
||||
static StreamVariable STUB = new StreamVariable(PsiType.VOID) {
|
||||
static StreamVariable STUB = new StreamVariable("") {
|
||||
@Override
|
||||
public void addBestNameCandidate(String candidate) {
|
||||
}
|
||||
@@ -60,8 +59,13 @@ class StreamVariable {
|
||||
private Collection<String> myBestCandidates = new LinkedHashSet<>();
|
||||
private Collection<String> myOtherCandidates = new LinkedHashSet<>();
|
||||
|
||||
StreamVariable(@NotNull PsiType type) {
|
||||
myType = type.getCanonicalText();
|
||||
StreamVariable(@NotNull String type) {
|
||||
myType = type;
|
||||
}
|
||||
|
||||
StreamVariable(@NotNull String type, @NotNull String name) {
|
||||
myType = type;
|
||||
myName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+573
-98
@@ -18,13 +18,20 @@ package com.intellij.codeInspection.streamToLoop;
|
||||
import com.intellij.codeInspection.streamToLoop.StreamToLoopInspection.StreamToLoopReplacementContext;
|
||||
import com.intellij.codeInspection.util.OptionalUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTypesUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.siyeh.ig.psiutils.BoolUtils;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @author Tagir Valeev
|
||||
@@ -45,6 +52,10 @@ abstract class TerminalOperation extends Operation {
|
||||
return true;
|
||||
}
|
||||
|
||||
CollectorOperation asCollector() {
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract String generate(StreamVariable inVar, StreamToLoopReplacementContext context);
|
||||
|
||||
@Nullable
|
||||
@@ -61,19 +72,18 @@ abstract class TerminalOperation extends Operation {
|
||||
return new AccumulatedTerminalOperation("count", "long", "0", "{acc}++;");
|
||||
}
|
||||
if(name.equals("sum") && args.length == 0) {
|
||||
return new AccumulatedTerminalOperation("sum", resultType.getCanonicalText(), "0", "{acc}+={item};");
|
||||
return AccumulatedTerminalOperation.summing(resultType);
|
||||
}
|
||||
if(name.equals("average") && args.length == 0) {
|
||||
if(elementType.equals(PsiType.DOUBLE)) {
|
||||
return new AverageTerminalOperation(true);
|
||||
return new AverageTerminalOperation(true, true);
|
||||
}
|
||||
else if(elementType.equals(PsiType.INT) || elementType.equals(PsiType.LONG)) {
|
||||
return new AverageTerminalOperation(false);
|
||||
return new AverageTerminalOperation(false, true);
|
||||
}
|
||||
}
|
||||
if(name.equals("summaryStatistics") && args.length == 0) {
|
||||
return new AccumulatedTerminalOperation("stat", resultType.getCanonicalText(), "new " + resultType.getCanonicalText() + "()",
|
||||
"{acc}.accept({item});");
|
||||
return AccumulatedTerminalOperation.summarizing(resultType);
|
||||
}
|
||||
if((name.equals("findFirst") || name.equals("findAny")) && args.length == 0) {
|
||||
return new FindTerminalOperation(resultType.getCanonicalText());
|
||||
@@ -90,11 +100,7 @@ abstract class TerminalOperation extends Operation {
|
||||
}
|
||||
}
|
||||
if(args.length == 1) {
|
||||
PsiType optionalElementType = OptionalUtil.getOptionalElementType(resultType);
|
||||
FunctionHelper fn = FunctionHelper.create(args[0], 2);
|
||||
if(fn != null && optionalElementType != null) {
|
||||
return new ReduceToOptionalTerminalOperation(fn, optionalElementType.getCanonicalText());
|
||||
}
|
||||
return ReduceToOptionalTerminalOperation.create(args[0], resultType);
|
||||
}
|
||||
}
|
||||
if(name.equals("toArray") && args.length < 2) {
|
||||
@@ -120,60 +126,173 @@ abstract class TerminalOperation extends Operation {
|
||||
"{acc}.toArray("+arr+")");
|
||||
}
|
||||
}
|
||||
if(name.equals("collect") && args.length == 3) {
|
||||
FunctionHelper supplier = FunctionHelper.create(args[0], 0);
|
||||
if(supplier == null) return null;
|
||||
FunctionHelper accumulator = FunctionHelper.create(args[1], 2);
|
||||
if(accumulator == null) return null;
|
||||
return new ExplicitCollectTerminalOperation(supplier, accumulator, resultType.getCanonicalText());
|
||||
if ((name.equals("max") || name.equals("min")) && args.length < 2) {
|
||||
return MinMaxTerminalOperation.create(args.length == 1 ? args[0] : null, elementType.getCanonicalText(), name.equals("max"));
|
||||
}
|
||||
if(name.equals("collect") && args.length == 1) {
|
||||
if(args[0] instanceof PsiMethodCallExpression) {
|
||||
PsiMethodCallExpression collectorCall = (PsiMethodCallExpression)args[0];
|
||||
PsiExpression[] collectorArgs = collectorCall.getArgumentList().getExpressions();
|
||||
PsiMethod collector = collectorCall.resolveMethod();
|
||||
if(collector == null) return null;
|
||||
PsiClass collectorClass = collector.getContainingClass();
|
||||
if(collectorClass != null && CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS.equals(collectorClass.getQualifiedName())) {
|
||||
if(collector.getName().equals("toList") && collectorArgs.length == 0) {
|
||||
return AccumulatedTerminalOperation.toCollection(resultType, CommonClassNames.JAVA_UTIL_ARRAY_LIST, "list");
|
||||
}
|
||||
if(collector.getName().equals("toSet") && collectorArgs.length == 0) {
|
||||
return AccumulatedTerminalOperation.toCollection(resultType, CommonClassNames.JAVA_UTIL_HASH_SET, "set");
|
||||
}
|
||||
if(collector.getName().equals("toCollection") && collectorArgs.length == 1) {
|
||||
FunctionHelper fn = FunctionHelper.create(collectorArgs[0], 0);
|
||||
if(fn != null) {
|
||||
return new ToCollectionTerminalOperation(fn, resultType);
|
||||
}
|
||||
}
|
||||
if(collector.getName().equals("reducing") && collectorArgs.length == 2) {
|
||||
FunctionHelper fn = FunctionHelper.create(collectorArgs[1], 2);
|
||||
if(fn != null) {
|
||||
return new ReduceTerminalOperation(collectorArgs[0], fn, resultType.getCanonicalText());
|
||||
}
|
||||
}
|
||||
if(collector.getName().equals("reducing") && collectorArgs.length == 1) {
|
||||
PsiType optionalElementType = OptionalUtil.getOptionalElementType(resultType);
|
||||
FunctionHelper fn = FunctionHelper.create(collectorArgs[0], 2);
|
||||
if(fn != null && optionalElementType != null) {
|
||||
return new ReduceToOptionalTerminalOperation(fn, optionalElementType.getCanonicalText());
|
||||
}
|
||||
}
|
||||
if(collector.getName().equals("joining")) {
|
||||
if(collectorArgs.length == 0) {
|
||||
return new AccumulatedTerminalOperation("sb", CommonClassNames.JAVA_LANG_STRING_BUILDER,
|
||||
"new " + CommonClassNames.JAVA_LANG_STRING_BUILDER + "()", "{acc}.append({item});",
|
||||
"{acc}.toString()");
|
||||
}
|
||||
if(collectorArgs.length == 1 || collectorArgs.length == 3) {
|
||||
String initializer = "new java.util.StringJoiner(" + StreamEx.of(collectorArgs).map(PsiElement::getText).joining(",") + ")";
|
||||
return new AccumulatedTerminalOperation("joiner", "java.util.StringJoiner", initializer,
|
||||
"{acc}.add({item});", "{acc}.toString()");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (name.equals("collect")) {
|
||||
if (args.length == 3) {
|
||||
FunctionHelper supplier = FunctionHelper.create(args[0], 0);
|
||||
if (supplier == null) return null;
|
||||
FunctionHelper accumulator = FunctionHelper.create(args[1], 2);
|
||||
if (accumulator == null) return null;
|
||||
return new ExplicitCollectTerminalOperation(supplier, accumulator);
|
||||
}
|
||||
if (args.length == 1) {
|
||||
return fromCollector(elementType.getCanonicalText(), resultType, args[0]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Contract("_, _, null -> null")
|
||||
@Nullable
|
||||
private static TerminalOperation fromCollector(@NotNull String elementType, @NotNull PsiType resultType, PsiExpression expr) {
|
||||
if (!(expr instanceof PsiMethodCallExpression)) return null;
|
||||
PsiMethodCallExpression collectorCall = (PsiMethodCallExpression)expr;
|
||||
PsiExpression[] collectorArgs = collectorCall.getArgumentList().getExpressions();
|
||||
PsiMethod collector = collectorCall.resolveMethod();
|
||||
if (collector == null) return null;
|
||||
PsiClass collectorClass = collector.getContainingClass();
|
||||
if (collectorClass != null && CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS.equals(collectorClass.getQualifiedName())) {
|
||||
return fromCollector(elementType, resultType, collector, collectorArgs);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static TerminalOperation fromCollector(@NotNull String elementType,
|
||||
@NotNull PsiType resultType,
|
||||
PsiMethod collector,
|
||||
PsiExpression[] collectorArgs) {
|
||||
String collectorName = collector.getName();
|
||||
FunctionHelper fn;
|
||||
switch (collectorName) {
|
||||
case "toList":
|
||||
if (collectorArgs.length != 0) return null;
|
||||
return AccumulatedTerminalOperation.toList(resultType);
|
||||
case "toSet":
|
||||
if (collectorArgs.length != 0) return null;
|
||||
return AccumulatedTerminalOperation.toCollection(resultType, CommonClassNames.JAVA_UTIL_HASH_SET, "set");
|
||||
case "toCollection":
|
||||
if (collectorArgs.length != 1) return null;
|
||||
fn = FunctionHelper.create(collectorArgs[0], 0);
|
||||
return fn == null ? null : new ToCollectionTerminalOperation(fn);
|
||||
case "toMap": {
|
||||
if (collectorArgs.length < 2 || collectorArgs.length > 4) return null;
|
||||
FunctionHelper key = FunctionHelper.create(collectorArgs[0], 1);
|
||||
FunctionHelper value = FunctionHelper.create(collectorArgs[1], 1);
|
||||
if(key == null || value == null) return null;
|
||||
PsiExpression merger = collectorArgs.length > 2 ? collectorArgs[2] : null;
|
||||
FunctionHelper supplier = collectorArgs.length == 4
|
||||
? FunctionHelper.create(collectorArgs[3], 0)
|
||||
: FunctionHelper.hashMapSupplier(resultType);
|
||||
if(supplier == null) return null;
|
||||
return new ToMapTerminalOperation(key, value, merger, supplier, resultType);
|
||||
}
|
||||
case "reducing":
|
||||
switch (collectorArgs.length) {
|
||||
case 1:
|
||||
return ReduceToOptionalTerminalOperation.create(collectorArgs[0], resultType);
|
||||
case 2:
|
||||
fn = FunctionHelper.create(collectorArgs[1], 2);
|
||||
return fn == null ? null : new ReduceTerminalOperation(collectorArgs[0], fn, resultType.getCanonicalText());
|
||||
case 3:
|
||||
FunctionHelper mapper = FunctionHelper.create(collectorArgs[1], 1);
|
||||
fn = FunctionHelper.create(collectorArgs[2], 2);
|
||||
return fn == null || mapper == null
|
||||
? null
|
||||
: new MappingTerminalOperation(mapper, new ReduceTerminalOperation(collectorArgs[0], fn, resultType.getCanonicalText()));
|
||||
}
|
||||
return null;
|
||||
case "counting":
|
||||
if (collectorArgs.length != 0) return null;
|
||||
return new AccumulatedTerminalOperation("count", "long", "0", "{acc}++;");
|
||||
case "summingInt":
|
||||
case "summingLong":
|
||||
case "summingDouble": {
|
||||
if (collectorArgs.length != 1) return null;
|
||||
fn = FunctionHelper.create(collectorArgs[0], 1);
|
||||
PsiPrimitiveType type = PsiPrimitiveType.getUnboxedType(resultType);
|
||||
return fn == null || type == null ? null : new InlineMappingTerminalOperation(fn, AccumulatedTerminalOperation.summing(type));
|
||||
}
|
||||
case "summarizingInt":
|
||||
case "summarizingLong":
|
||||
case "summarizingDouble": {
|
||||
if (collectorArgs.length != 1) return null;
|
||||
fn = FunctionHelper.create(collectorArgs[0], 1);
|
||||
return fn == null ? null : new InlineMappingTerminalOperation(fn, AccumulatedTerminalOperation.summarizing(resultType));
|
||||
}
|
||||
case "averagingInt":
|
||||
case "averagingLong":
|
||||
case "averagingDouble": {
|
||||
if (collectorArgs.length != 1) return null;
|
||||
fn = FunctionHelper.create(collectorArgs[0], 1);
|
||||
return fn == null
|
||||
? null
|
||||
: new InlineMappingTerminalOperation(fn, new AverageTerminalOperation(collectorName.equals("averagingDouble"), false));
|
||||
}
|
||||
case "mapping": {
|
||||
if (collectorArgs.length != 2) return null;
|
||||
fn = FunctionHelper.create(collectorArgs[0], 1);
|
||||
if (fn == null) return null;
|
||||
TerminalOperation downstreamOp = fromCollector(fn.getResultType(), resultType, collectorArgs[1]);
|
||||
return downstreamOp == null ? null : new MappingTerminalOperation(fn, downstreamOp);
|
||||
}
|
||||
case "groupingBy":
|
||||
case "partitioningBy": {
|
||||
if (collectorArgs.length == 0 || collectorArgs.length > 3
|
||||
|| collectorArgs.length == 3 && collectorName.equals("partitioningBy")) return null;
|
||||
fn = FunctionHelper.create(collectorArgs[0], 1);
|
||||
if (fn == null) return null;
|
||||
if (!(resultType instanceof PsiClassType)) return null;
|
||||
PsiClass aClass = ((PsiClassType)resultType).resolve();
|
||||
if (aClass == null) return null;
|
||||
PsiSubstitutor substitutor = ((PsiClassType)resultType).resolveGenerics().getSubstitutor();
|
||||
PsiClass mapClass =
|
||||
JavaPsiFacade.getInstance(aClass.getProject()).findClass(CommonClassNames.JAVA_UTIL_MAP, aClass.getResolveScope());
|
||||
if (mapClass == null) return null;
|
||||
PsiTypeParameter[] parameters = mapClass.getTypeParameters();
|
||||
if (parameters.length != 2) return null;
|
||||
PsiType resultSubType = substitutor.substitute(parameters[1]);
|
||||
if (resultSubType == null) return null;
|
||||
CollectorOperation downstreamCollector;
|
||||
if (collectorArgs.length == 1) {
|
||||
downstreamCollector = AccumulatedTerminalOperation.toList(resultSubType).asCollector();
|
||||
}
|
||||
else {
|
||||
PsiExpression downstream = collectorArgs[collectorArgs.length - 1];
|
||||
TerminalOperation downstreamOp = fromCollector(elementType, resultSubType, downstream);
|
||||
if (downstreamOp == null) return null;
|
||||
downstreamCollector = downstreamOp.asCollector();
|
||||
}
|
||||
if (downstreamCollector == null) return null;
|
||||
if (collectorName.equals("partitioningBy")) {
|
||||
return new PartitionByTerminalOperation(fn, resultType, downstreamCollector);
|
||||
}
|
||||
FunctionHelper supplier = collectorArgs.length == 3
|
||||
? FunctionHelper.create(collectorArgs[1], 0)
|
||||
: FunctionHelper.hashMapSupplier(resultType);
|
||||
return new GroupByTerminalOperation(fn, supplier, resultType, downstreamCollector);
|
||||
}
|
||||
case "minBy":
|
||||
case "maxBy":
|
||||
if (collectorArgs.length != 1) return null;
|
||||
return MinMaxTerminalOperation.create(collectorArgs[0], elementType, collectorName.equals("maxBy"));
|
||||
case "joining":
|
||||
switch (collectorArgs.length) {
|
||||
case 0:
|
||||
return new AccumulatedTerminalOperation("sb", CommonClassNames.JAVA_LANG_STRING_BUILDER,
|
||||
"new " + CommonClassNames.JAVA_LANG_STRING_BUILDER + "()",
|
||||
"{acc}.append({item});",
|
||||
"{acc}.toString()");
|
||||
case 1:
|
||||
case 3:
|
||||
String initializer =
|
||||
"new java.util.StringJoiner(" + StreamEx.of(collectorArgs).map(PsiElement::getText).joining(",") + ")";
|
||||
return new AccumulatedTerminalOperation("joiner", "java.util.StringJoiner", initializer,
|
||||
"{acc}.add({item});", "{acc}.toString()");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -190,7 +309,7 @@ abstract class TerminalOperation extends Operation {
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
FunctionHelper.processUsedNames(myIdentity, usedNameConsumer);
|
||||
myUpdater.registerUsedNames(usedNameConsumer);
|
||||
}
|
||||
@@ -213,7 +332,7 @@ abstract class TerminalOperation extends Operation {
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
myUpdater.registerUsedNames(usedNameConsumer);
|
||||
}
|
||||
|
||||
@@ -222,8 +341,7 @@ abstract class TerminalOperation extends Operation {
|
||||
String seen = context.declare("seen", "boolean", "false");
|
||||
String accumulator = context.declareResult("acc", myType, TypeConversionUtil.isPrimitive(myType) ? "0" : "null");
|
||||
myUpdater.transform(context, accumulator, inVar.getName());
|
||||
String optionalClass = OptionalUtil.getOptionalClass(myType);
|
||||
context.setFinisher("(" + seen + "?" + optionalClass + ".of(" + accumulator + "):" + optionalClass + ".empty())");
|
||||
context.setOptionalUnwrapperFinisher(seen, accumulator, myType);
|
||||
return "if(!" + seen + ") {\n" +
|
||||
seen + "=true;\n" +
|
||||
accumulator + "=" + inVar + ";\n" +
|
||||
@@ -231,21 +349,29 @@ abstract class TerminalOperation extends Operation {
|
||||
accumulator + "=" + myUpdater.getText() + ";\n" +
|
||||
"}\n";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static ReduceToOptionalTerminalOperation create(PsiExpression arg, PsiType resultType) {
|
||||
PsiType optionalElementType = OptionalUtil.getOptionalElementType(resultType);
|
||||
FunctionHelper fn = FunctionHelper.create(arg, 2);
|
||||
if(fn != null && optionalElementType != null) {
|
||||
return new ReduceToOptionalTerminalOperation(fn, optionalElementType.getCanonicalText());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static class ExplicitCollectTerminalOperation extends TerminalOperation {
|
||||
private final FunctionHelper mySupplier;
|
||||
private final FunctionHelper myAccumulator;
|
||||
private final String myResultType;
|
||||
|
||||
public ExplicitCollectTerminalOperation(FunctionHelper supplier, FunctionHelper accumulator, String resultType) {
|
||||
public ExplicitCollectTerminalOperation(FunctionHelper supplier, FunctionHelper accumulator) {
|
||||
mySupplier = supplier;
|
||||
myAccumulator = accumulator;
|
||||
myResultType = resultType;
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
mySupplier.registerUsedNames(usedNameConsumer);
|
||||
myAccumulator.registerUsedNames(usedNameConsumer);
|
||||
}
|
||||
@@ -258,26 +384,32 @@ abstract class TerminalOperation extends Operation {
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
mySupplier.transform(context);
|
||||
String candidate = myAccumulator.getParameterName(0);
|
||||
String acc = context.declareResult(candidate == null ? "acc" : candidate, myResultType, mySupplier.getText());
|
||||
String candidate = mySupplier.suggestFinalOutputNames(context, myAccumulator.getParameterName(0), "acc").get(0);
|
||||
String acc = context.declareResult(candidate, mySupplier.getResultType(), mySupplier.getText());
|
||||
myAccumulator.transform(context, acc, inVar.getName());
|
||||
return myAccumulator.getText()+";\n";
|
||||
}
|
||||
}
|
||||
|
||||
static class AverageTerminalOperation extends TerminalOperation {
|
||||
private boolean myDoubleAccumulator;
|
||||
private final boolean myDoubleAccumulator;
|
||||
private final boolean myUseOptional;
|
||||
|
||||
public AverageTerminalOperation(boolean doubleAccumulator) {
|
||||
public AverageTerminalOperation(boolean doubleAccumulator, boolean useOptional) {
|
||||
myDoubleAccumulator = doubleAccumulator;
|
||||
myUseOptional = useOptional;
|
||||
}
|
||||
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
String sum = context.declareResult("sum", myDoubleAccumulator ? "double" : "long", "0");
|
||||
String count = context.declare("count", "long", "0");
|
||||
context.setFinisher("("+count+"==0?java.util.OptionalDouble.empty():"
|
||||
+"java.util.OptionalDouble.of("+(myDoubleAccumulator?"":"(double)")+sum+"/"+count+"))");
|
||||
String emptyCheck = 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 + ")");
|
||||
return sum + "+=" + inVar + ";\n" + count + "++;\n";
|
||||
}
|
||||
}
|
||||
@@ -343,7 +475,7 @@ abstract class TerminalOperation extends Operation {
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
myFn.registerUsedNames(usedNameConsumer);
|
||||
}
|
||||
|
||||
@@ -369,7 +501,56 @@ abstract class TerminalOperation extends Operation {
|
||||
}
|
||||
}
|
||||
|
||||
static class AccumulatedTerminalOperation extends TerminalOperation {
|
||||
interface CollectorOperation {
|
||||
// Non-trivial finishers are not supported
|
||||
default void transform(StreamToLoopReplacementContext context, String item) {}
|
||||
default void suggestNames(StreamVariable inVar, StreamVariable outVar) {}
|
||||
default void registerUsedNames(Consumer<String> usedNameConsumer) {}
|
||||
String getSupplier();
|
||||
String getAccumulator(String acc, String item);
|
||||
}
|
||||
|
||||
abstract static class CollectorBasedTerminalOperation extends TerminalOperation implements CollectorOperation {
|
||||
final String myType;
|
||||
final Function<StreamToLoopReplacementContext, String> myAccNameSupplier;
|
||||
final FunctionHelper mySupplier;
|
||||
|
||||
CollectorBasedTerminalOperation(String type, Function<StreamToLoopReplacementContext, String> accNameSupplier,
|
||||
FunctionHelper accSupplier) {
|
||||
myType = type;
|
||||
myAccNameSupplier = accNameSupplier;
|
||||
mySupplier = accSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
transform(context, inVar.getName());
|
||||
String acc = context.declareResult(myAccNameSupplier.apply(context), myType, getSupplier());
|
||||
return getAccumulator(acc, inVar.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
CollectorOperation asCollector() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
mySupplier.registerUsedNames(usedNameConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(StreamToLoopReplacementContext context, String item) {
|
||||
mySupplier.transform(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSupplier() {
|
||||
return mySupplier.getText();
|
||||
}
|
||||
}
|
||||
|
||||
static class AccumulatedTerminalOperation extends TerminalOperation implements CollectorOperation {
|
||||
private String myAccName;
|
||||
private String myAccType;
|
||||
private String myAccInitializer;
|
||||
@@ -404,32 +585,326 @@ abstract class TerminalOperation extends Operation {
|
||||
return myUpdateTemplate.replace("{item}", inVar.getName()).replace("{acc}", varName);
|
||||
}
|
||||
|
||||
public static AccumulatedTerminalOperation toCollection(PsiType collectionType, String implementationType, String varName) {
|
||||
return new AccumulatedTerminalOperation(varName, collectionType.getCanonicalText(), "new " + implementationType + "<>()",
|
||||
"{acc}.add({item});");
|
||||
}
|
||||
}
|
||||
|
||||
static class ToCollectionTerminalOperation extends TerminalOperation {
|
||||
private final String myType;
|
||||
private final FunctionHelper myFn;
|
||||
|
||||
public ToCollectionTerminalOperation(FunctionHelper fn, PsiType callType) {
|
||||
myFn = fn;
|
||||
myType = callType.getCanonicalText();
|
||||
@Override
|
||||
CollectorOperation asCollector() {
|
||||
return myFinisherTemplate.equals("{acc}") && PsiTypesUtil.boxIfPossible(myAccType).equals(myAccType) ? this : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
myFn.registerUsedNames(usedNameConsumer);
|
||||
public String getSupplier() {
|
||||
return myAccInitializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccumulator(String acc, String item) {
|
||||
return myUpdateTemplate.replace("{acc}", acc).replace("{item}", item);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static AccumulatedTerminalOperation toCollection(PsiType collectionType, String implementationType, String varName) {
|
||||
return new AccumulatedTerminalOperation(varName, collectionType.getCanonicalText(), "new " + implementationType + "<>()",
|
||||
"{acc}.add({item});");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static AccumulatedTerminalOperation toList(@NotNull PsiType resultType) {
|
||||
return toCollection(resultType, CommonClassNames.JAVA_UTIL_ARRAY_LIST, "list");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static AccumulatedTerminalOperation summing(PsiType type) {
|
||||
return new AccumulatedTerminalOperation("sum", type.getCanonicalText(), "0", "{acc}+={item};");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static AccumulatedTerminalOperation summarizing(@NotNull PsiType resultType) {
|
||||
return new AccumulatedTerminalOperation("stat", resultType.getCanonicalText(), "new " + resultType.getCanonicalText() + "()",
|
||||
"{acc}.accept({item});");
|
||||
}
|
||||
}
|
||||
|
||||
static class ToCollectionTerminalOperation extends CollectorBasedTerminalOperation {
|
||||
public ToCollectionTerminalOperation(FunctionHelper fn) {
|
||||
super(fn.getResultType(), context -> fn.suggestFinalOutputNames(context, null, "collection").get(0), fn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccumulator(String acc, String item) {
|
||||
return acc+".add("+item+");\n";
|
||||
}
|
||||
}
|
||||
|
||||
static class MinMaxTerminalOperation extends TerminalOperation {
|
||||
private String myType;
|
||||
private String myTemplate;
|
||||
private String myComparatorType;
|
||||
private @Nullable PsiExpression myComparator;
|
||||
|
||||
public MinMaxTerminalOperation(String type, String template, @Nullable PsiExpression comparator) {
|
||||
myType = type;
|
||||
myTemplate = template;
|
||||
myComparator = comparator;
|
||||
if(comparator != null) {
|
||||
PsiType comparatorType = comparator.getType();
|
||||
if(comparatorType != null) {
|
||||
myComparatorType = comparatorType.getCanonicalText();
|
||||
} else {
|
||||
myComparatorType = CommonClassNames.JAVA_UTIL_COMPARATOR+"<"+myType+">";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
if(myComparator != null) {
|
||||
FunctionHelper.processUsedNames(myComparator, usedNameConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
// TODO: remove redundant type arguments
|
||||
myFn.transform(context);
|
||||
String collection = context.declareResult("collection", myType, myFn.getText());
|
||||
return collection+".add("+inVar+");\n";
|
||||
String comparator = "";
|
||||
if(myComparator != null) {
|
||||
if(ExpressionUtils.isSimpleExpression(myComparator)) {
|
||||
comparator = myComparator.getText();
|
||||
} else {
|
||||
comparator = context.declare("comparator", myComparatorType, myComparator.getText());
|
||||
}
|
||||
}
|
||||
String seen = context.declare("seen", "boolean", "false");
|
||||
String best = context.declareResult("best", myType, TypeConversionUtil.isPrimitive(myType) ? "0" : "null");
|
||||
String type = myType;
|
||||
context.setOptionalUnwrapperFinisher(seen, best, type);
|
||||
return "if(!"+seen+" || "+myTemplate.replace("{best}", best).replace("{item}", inVar.getName()).replace("{comparator}", comparator)+") {\n" +
|
||||
seen+"=true;\n"+
|
||||
best+"="+inVar+";\n}\n";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static MinMaxTerminalOperation create(@Nullable PsiExpression comparator, String elementType, boolean max) {
|
||||
String sign = max ? ">" : "<";
|
||||
if(comparator == null) {
|
||||
if ("int".equals(elementType) || "long".equals(elementType)) {
|
||||
return new MinMaxTerminalOperation(elementType, "{item}" + sign + "{best}", null);
|
||||
}
|
||||
if ("double".equals(elementType)) {
|
||||
return new MinMaxTerminalOperation(elementType, "java.lang.Double.compare({item},{best})" + sign + "0", null);
|
||||
}
|
||||
} else if(InheritanceUtil.isInheritor(PsiUtil.resolveClassInClassTypeOnly(comparator.getType()), false,
|
||||
CommonClassNames.JAVA_UTIL_COMPARATOR)) {
|
||||
return new MinMaxTerminalOperation(elementType, "{comparator}.compare({item},{best})" + sign + "0", comparator);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static class ToMapTerminalOperation extends CollectorBasedTerminalOperation {
|
||||
private final FunctionHelper myKeyExtractor, myValueExtractor;
|
||||
private final PsiExpression myMerger;
|
||||
|
||||
ToMapTerminalOperation(FunctionHelper keyExtractor,
|
||||
FunctionHelper valueExtractor,
|
||||
PsiExpression merger,
|
||||
FunctionHelper supplier,
|
||||
PsiType resultType) {
|
||||
super(resultType.getCanonicalText(), context -> "map", supplier);
|
||||
myKeyExtractor = keyExtractor;
|
||||
myValueExtractor = valueExtractor;
|
||||
myMerger = merger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
super.registerUsedNames(usedNameConsumer);
|
||||
myKeyExtractor.registerUsedNames(usedNameConsumer);
|
||||
myValueExtractor.registerUsedNames(usedNameConsumer);
|
||||
if(myMerger != null) FunctionHelper.processUsedNames(myMerger, usedNameConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestNames(StreamVariable inVar, StreamVariable outVar) {
|
||||
myKeyExtractor.suggestVariableName(inVar, 0);
|
||||
myValueExtractor.suggestVariableName(inVar, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(StreamToLoopReplacementContext context, String item) {
|
||||
super.transform(context, item);
|
||||
myKeyExtractor.transform(context, item);
|
||||
myValueExtractor.transform(context, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccumulator(String map, String item) {
|
||||
if(myMerger == null) {
|
||||
return "if("+map+".put("+myKeyExtractor.getText()+","+myValueExtractor.getText()+")!=null) {\n"+
|
||||
"throw new java.lang.IllegalStateException(\"Duplicate key\");\n}\n";
|
||||
}
|
||||
return map+".merge("+myKeyExtractor.getText()+","+myValueExtractor.getText()+","+myMerger.getText()+");\n";
|
||||
}
|
||||
}
|
||||
|
||||
static class GroupByTerminalOperation extends CollectorBasedTerminalOperation {
|
||||
private final CollectorOperation myCollector;
|
||||
private FunctionHelper myKeyExtractor;
|
||||
private String myKeyVar;
|
||||
|
||||
public GroupByTerminalOperation(FunctionHelper keyExtractor, FunctionHelper supplier, PsiType resultType, CollectorOperation collector) {
|
||||
super(resultType.getCanonicalText(), context -> "map", supplier);
|
||||
myKeyExtractor = keyExtractor;
|
||||
myCollector = collector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
super.registerUsedNames(usedNameConsumer);
|
||||
myKeyExtractor.registerUsedNames(usedNameConsumer);
|
||||
myCollector.registerUsedNames(usedNameConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestNames(StreamVariable inVar, StreamVariable outVar) {
|
||||
myKeyExtractor.suggestVariableName(inVar, 0);
|
||||
myCollector.suggestNames(inVar, outVar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(StreamToLoopReplacementContext context, String item) {
|
||||
super.transform(context, item);
|
||||
myKeyExtractor.transform(context, item);
|
||||
myCollector.transform(context, item);
|
||||
myKeyVar = context.registerVarName(Arrays.asList("k", "key"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccumulator(String map, String item) {
|
||||
String acc = map+".computeIfAbsent("+myKeyExtractor.getText()+","+myKeyVar+"->"+myCollector.getSupplier()+")";
|
||||
return myCollector.getAccumulator(acc, item);
|
||||
}
|
||||
}
|
||||
|
||||
static class PartitionByTerminalOperation extends TerminalOperation {
|
||||
private final String myResultType;
|
||||
private final CollectorOperation myCollector;
|
||||
private FunctionHelper myPredicate;
|
||||
|
||||
public PartitionByTerminalOperation(FunctionHelper predicate, PsiType resultType, CollectorOperation collector) {
|
||||
myPredicate = predicate;
|
||||
myResultType = resultType.getCanonicalText();
|
||||
myCollector = collector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
myPredicate.registerUsedNames(usedNameConsumer);
|
||||
myCollector.registerUsedNames(usedNameConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestNames(StreamVariable inVar, StreamVariable outVar) {
|
||||
myPredicate.suggestVariableName(inVar, 0);
|
||||
myCollector.suggestNames(inVar, outVar);
|
||||
}
|
||||
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
String map = context.declareResult("map", myResultType, "new java.util.HashMap<>()");
|
||||
myPredicate.transform(context, inVar.getName());
|
||||
myCollector.transform(context, inVar.getName());
|
||||
context.addInitStep(map+".put(false, "+myCollector.getSupplier()+");");
|
||||
context.addInitStep(map+".put(true, "+myCollector.getSupplier()+");");
|
||||
return myCollector.getAccumulator(map + ".get(" + myPredicate.getText() + ")", inVar.getName());
|
||||
}
|
||||
}
|
||||
|
||||
abstract static class AbstractMappingTerminalOperation extends TerminalOperation implements CollectorOperation {
|
||||
final FunctionHelper myMapper;
|
||||
final TerminalOperation myDownstream;
|
||||
final CollectorOperation myDownstreamCollector;
|
||||
|
||||
AbstractMappingTerminalOperation(FunctionHelper mapper, TerminalOperation downstream) {
|
||||
myMapper = mapper;
|
||||
myDownstream = downstream;
|
||||
myDownstreamCollector = downstream.asCollector();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
myMapper.registerUsedNames(usedNameConsumer);
|
||||
myDownstream.registerUsedNames(usedNameConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestNames(StreamVariable inVar, StreamVariable outVar) {
|
||||
myMapper.suggestVariableName(inVar, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
CollectorOperation asCollector() {
|
||||
return myDownstreamCollector == null ? null : this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSupplier() {
|
||||
return myDownstreamCollector.getSupplier();
|
||||
}
|
||||
}
|
||||
|
||||
static class MappingTerminalOperation extends AbstractMappingTerminalOperation {
|
||||
private StreamVariable myVariable;
|
||||
|
||||
MappingTerminalOperation(FunctionHelper mapper, TerminalOperation downstream) {
|
||||
super(mapper, downstream);
|
||||
}
|
||||
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
createVariable(context, inVar.getName());
|
||||
return myVariable.getDeclaration() + "=" + myMapper.getText() + ";\n" + myDownstream.generate(myVariable, context);
|
||||
}
|
||||
|
||||
private void createVariable(StreamToLoopReplacementContext context, String item) {
|
||||
myMapper.transform(context, item);
|
||||
myVariable = new StreamVariable(myMapper.getResultType());
|
||||
myDownstream.suggestNames(myVariable, StreamVariable.STUB);
|
||||
myMapper.suggestFinalOutputNames(context, null, null).forEach(myVariable::addOtherNameCandidate);
|
||||
myVariable.register(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(StreamToLoopReplacementContext context, String item) {
|
||||
createVariable(context, item);
|
||||
myDownstreamCollector.transform(context, myVariable.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccumulator(String acc, String item) {
|
||||
return myVariable.getDeclaration() + "=" + myMapper.getText() + ";\n" +
|
||||
myDownstreamCollector.getAccumulator(acc, myVariable.getName());
|
||||
}
|
||||
}
|
||||
|
||||
static class InlineMappingTerminalOperation extends AbstractMappingTerminalOperation {
|
||||
InlineMappingTerminalOperation(FunctionHelper mapper, TerminalOperation downstream) {
|
||||
super(mapper, downstream);
|
||||
}
|
||||
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
myMapper.transform(context, inVar.getName());
|
||||
StreamVariable updatedVar = new StreamVariable(myMapper.getResultType(), myMapper.getText());
|
||||
return myDownstream.generate(updatedVar, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(StreamToLoopReplacementContext context, String item) {
|
||||
myMapper.transform(context, item);
|
||||
myDownstreamCollector.transform(context, myMapper.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccumulator(String acc, String item) {
|
||||
return myDownstreamCollector.getAccumulator(acc, myMapper.getText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,7 +921,7 @@ abstract class TerminalOperation extends Operation {
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
public void registerUsedNames(Consumer<String> usedNameConsumer) {
|
||||
myFn.registerUsedNames(usedNameConsumer);
|
||||
}
|
||||
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Main {
|
||||
public void test(String... list) {
|
||||
double sum = 0;
|
||||
long count = 0;
|
||||
for (String s : list) {
|
||||
if (Objects.nonNull(s)) {
|
||||
sum += 1.0 / s;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
System.out.println((count == 0 ? 0.0 : sum / count));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Main().test("a", "bbb", null, "cc", "dd", "eedasfasdfs");
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Main {
|
||||
public void test(String... list) {
|
||||
long sum = 0;
|
||||
long count = 0;
|
||||
for (String s : list) {
|
||||
if (Objects.nonNull(s)) {
|
||||
sum += s.length();
|
||||
count++;
|
||||
}
|
||||
}
|
||||
System.out.println((count == 0 ? 0.0 : (double) sum / count));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Main().test("a", "bbb", null, "cc", "dd", "eedasfasdfs");
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static long test(List<String> strings) {
|
||||
long count = 0;
|
||||
for (String s : strings) {
|
||||
if (!s.isEmpty()) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Optional<String> test(List<String> strings) {
|
||||
Comparator<String> comparator = Comparator.naturalOrder();
|
||||
boolean seen = false;
|
||||
String best = null;
|
||||
for (String s : strings) {
|
||||
if (!s.isEmpty()) {
|
||||
if (!seen || comparator.compare(s, best) > 0) {
|
||||
seen = true;
|
||||
best = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (seen ? Optional.of(best) : Optional.empty());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Main<T> {
|
||||
void test() {
|
||||
Integer acc = 0;
|
||||
for (String s : Arrays.asList("a", "bb", "ccc")) {
|
||||
Integer length = s.length();
|
||||
acc = Integer.sum(acc, length);
|
||||
}
|
||||
Integer totalLength = acc;
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.DoubleSummaryStatistics;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static DoubleSummaryStatistics test(List<String> strings) {
|
||||
DoubleSummaryStatistics stat = new DoubleSummaryStatistics();
|
||||
for (String str : strings) {
|
||||
if (Objects.nonNull(str)) {
|
||||
stat.accept(str.length() / 2.0);
|
||||
}
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList(null, null)));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Double test(List<String> strings) {
|
||||
double sum = 0;
|
||||
for (String string : strings) {
|
||||
if (Objects.nonNull(string)) {
|
||||
sum += string.length();
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList(null, null)));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public void test(List<String> list) {
|
||||
List<String> result = new ArrayList<>();
|
||||
Function<? super String, ? extends String> function = list.size() < 10 ? String::trim : Function.identity();
|
||||
for (String s : list) {
|
||||
String s1 = function.apply(s);
|
||||
result.add(s1);
|
||||
}
|
||||
System.out.println(result);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -10,8 +10,8 @@ public class Main {
|
||||
for (List<String> a : list) {
|
||||
if (a != null) {
|
||||
for (String s : a) {
|
||||
long l = s.length();
|
||||
stat.accept(l);
|
||||
long length = s.length();
|
||||
stat.accept(length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -10,8 +10,8 @@ public class Main {
|
||||
List<Integer> list = new ArrayList<>();
|
||||
for (int x : input) {
|
||||
if (x > 0) {
|
||||
Integer integer = x * 2;
|
||||
list.add(integer);
|
||||
Integer i = x * 2;
|
||||
list.add(i);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
|
||||
+6
-6
@@ -7,12 +7,12 @@ import java.util.stream.Stream;
|
||||
public class Main {
|
||||
private static long test(List<? extends String> list) {
|
||||
long count = 0;
|
||||
for (Object o : Arrays.<Object>asList(0, null, "1", list)) {
|
||||
for (Object o1 : Arrays.<Object>asList(o)) {
|
||||
for (Object o2 : Arrays.<Object>asList(o1)) {
|
||||
for (Object o3 : Arrays.<Object>asList(o2)) {
|
||||
for (Object o4 : Arrays.<Object>asList(o3)) {
|
||||
for (Object o5 : Arrays.<Object>asList(o4)) {
|
||||
for (Object o : Arrays.asList(0, null, "1", list)) {
|
||||
for (Object o1 : Arrays.asList(o)) {
|
||||
for (Object o2 : Arrays.asList(o1)) {
|
||||
for (Object o3 : Arrays.asList(o2)) {
|
||||
for (Object o4 : Arrays.asList(o3)) {
|
||||
for (Object o5 : Arrays.asList(o4)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> list) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (String x : list) {
|
||||
if (x != null) {
|
||||
Predicate<Integer> predicate = Predicate.isEqual(x.length());
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Integer integer = i;
|
||||
if (predicate.test(integer)) {
|
||||
result.add(integer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbbb", "cccccccccc", "dd", ""));
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -13,8 +13,8 @@ public class Main {
|
||||
for (List<String> lst : l) {
|
||||
if (lst != null) {
|
||||
for (String str : lst) {
|
||||
int i = str.length();
|
||||
stat.accept(i);
|
||||
int length = str.length();
|
||||
stat.accept(length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -10,8 +10,8 @@ public class Main {
|
||||
for (List<String> a : list) {
|
||||
if (a != null) {
|
||||
for (String s : a) {
|
||||
long l = s.length();
|
||||
stat.accept(l);
|
||||
long length = s.length();
|
||||
stat.accept(length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.SplittableRandom;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
Integer acc = 0;
|
||||
SplittableRandom splittableRandom = new SplittableRandom(1);
|
||||
for (long count = 100; count > 0; count--) {
|
||||
Integer integer = 500;
|
||||
acc = splittableRandom.nextInt(acc, integer);
|
||||
}
|
||||
int n1 = acc;
|
||||
System.out.println(n1);
|
||||
}
|
||||
}
|
||||
+4
-6
@@ -10,12 +10,10 @@ public class Main {
|
||||
Random r = new Random();
|
||||
DoubleSummaryStatistics stat = new DoubleSummaryStatistics();
|
||||
for (int x = 0; x < 10; x++) {
|
||||
double x1 = x;
|
||||
long limit = (long) x1;
|
||||
while (true) {
|
||||
double v = r.nextDouble() * x1;
|
||||
if (limit-- == 0) break;
|
||||
stat.accept(v);
|
||||
double v = x;
|
||||
for (long count = (long) v; count > 0; count--) {
|
||||
double v1 = r.nextDouble() * v;
|
||||
stat.accept(v1);
|
||||
}
|
||||
}
|
||||
return stat;
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Map<Integer, List<String>> test(List<String> strings) {
|
||||
Map<Integer, List<String>> map = new HashMap<>();
|
||||
for (String str : strings) {
|
||||
map.computeIfAbsent(str.length(), k -> new ArrayList<>()).add(str);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee")));
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Map<Integer, List<String>> test(List<String> strings, int k) {
|
||||
Map<Integer, List<String>> map = new HashMap<>();
|
||||
for (String string : strings) {
|
||||
map.computeIfAbsent(string.length(), key -> new ArrayList<>()).add(string);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee")));
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
private static TreeMap<Integer, LinkedHashSet<String>> getMap(List<String> strings) {
|
||||
TreeMap<Integer, LinkedHashSet<String>> map = new TreeMap<>(Comparator.reverseOrder());
|
||||
for (String string : strings) {
|
||||
map.computeIfAbsent(string.length(), k -> new LinkedHashSet<>()).add(string);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(getMap(Arrays.asList("a", "bbb", "cccc", "dddd", "ee", "e")));
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
Map<Integer, Map<Character, Set<String>>> map = new HashMap<>();
|
||||
for (String s : strings) {
|
||||
map.computeIfAbsent(s.length(), key -> new HashMap<>()).computeIfAbsent(s.charAt(0), k -> new HashSet<>()).add(s);
|
||||
}
|
||||
System.out.println(map);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd"));
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
private static TreeMap<Integer, List<Integer>> getMap(List<String> strings) {
|
||||
TreeMap<Integer, List<Integer>> map = new TreeMap<>(Comparator.reverseOrder());
|
||||
for (String string : strings) {
|
||||
Integer len = string.length();
|
||||
Integer integer = len * 2;
|
||||
map.computeIfAbsent(string.length(), k -> new ArrayList<>()).add(integer);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(getMap(Arrays.asList("a", "bbb", "cccc", "dddd", "ee", "e")));
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
Map<Integer, DoubleSummaryStatistics> map = new HashMap<>();
|
||||
for (String string : strings) {
|
||||
if (Objects.nonNull(string)) {
|
||||
map.computeIfAbsent(string.length(), k -> new DoubleSummaryStatistics()).accept(string.length());
|
||||
}
|
||||
}
|
||||
System.out.println(map);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd"));
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
Map<Integer, Map<Character, String>> map = new HashMap<>();
|
||||
for (String s : strings) {
|
||||
if (map.computeIfAbsent(s.length(), k -> new HashMap<>()).put(s.charAt(0), s) != null) {
|
||||
throw new IllegalStateException("Duplicate key");
|
||||
}
|
||||
}
|
||||
System.out.println(map);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd"));
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
Map<Integer, Set<String>> map = new HashMap<>();
|
||||
for (String string : strings) {
|
||||
if (Objects.nonNull(string)) {
|
||||
map.computeIfAbsent(string.length(), k -> new HashSet<>()).add(string);
|
||||
}
|
||||
}
|
||||
System.out.println(map);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd"));
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -9,8 +9,8 @@ public class Main {
|
||||
long limit = 20;
|
||||
for (String x = ""; ; x = x + "a") {
|
||||
if (limit-- == 0) break;
|
||||
int i = x.length();
|
||||
stat.accept(i);
|
||||
int length = x.length();
|
||||
stat.accept(length);
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
+2
-2
@@ -11,8 +11,8 @@ public class Main {
|
||||
long limitInner = limit;
|
||||
for (String x = ""; ; x = x + limit) {
|
||||
if (limitInner-- == 0) break;
|
||||
int i = x.length();
|
||||
stat.accept(i);
|
||||
int length = x.length();
|
||||
stat.accept(length);
|
||||
}
|
||||
}
|
||||
return stat;
|
||||
|
||||
+2
-2
@@ -12,8 +12,8 @@ public class Main {
|
||||
long limit = x;
|
||||
for (String s = String.valueOf(x); ; s = s + x) {
|
||||
if (limit-- == 0) break;
|
||||
int i = s.length();
|
||||
stat.accept(i);
|
||||
int length = s.length();
|
||||
stat.accept(length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -7,8 +7,8 @@ public class Main {
|
||||
private static long countNonEmpty(List<String> input) {
|
||||
long count = 0;
|
||||
for (String str : input) {
|
||||
String s = str.trim();
|
||||
if (!s.isEmpty()) {
|
||||
String trim = str.trim();
|
||||
if (!trim.isEmpty()) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
private static void getMap(List<String> strings) {
|
||||
List<Integer> list = new ArrayList<>();
|
||||
for (String string : strings) {
|
||||
Integer len = string.length();
|
||||
Integer integer = len * 2;
|
||||
list.add(integer);
|
||||
}
|
||||
System.out.println(list);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
getMap(Arrays.asList("a", "bbb", "cccc", "dddd", "ee", "e"));
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
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> comparator = Comparator.comparing(String::length);
|
||||
boolean seen = false;
|
||||
String best = null;
|
||||
for (String string : strings) {
|
||||
if (!seen || comparator.compare(string, best) > 0) {
|
||||
seen = true;
|
||||
best = string;
|
||||
}
|
||||
}
|
||||
return (seen ? Optional.of(best) : Optional.<String>empty()).orElse(null);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee")));
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.OptionalDouble;
|
||||
|
||||
public class Main {
|
||||
public static double test(List<String> strings) {
|
||||
boolean seen = false;
|
||||
double best = 0;
|
||||
for (String string : strings) {
|
||||
double v = string.length();
|
||||
if (!seen || Double.compare(v, best) > 0) {
|
||||
seen = true;
|
||||
best = v;
|
||||
}
|
||||
}
|
||||
return (seen ? OptionalDouble.of(best) : OptionalDouble.empty()).orElse(-1);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d")));
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
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) {
|
||||
boolean seen = false;
|
||||
String best = null;
|
||||
for (String string : strings) {
|
||||
if (!seen || cmp.compare(string, best) < 0) {
|
||||
seen = true;
|
||||
best = string;
|
||||
}
|
||||
}
|
||||
return (seen ? Optional.of(best) : Optional.<String>empty()).orElse(null);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList(), Comparator.comparing(String::length)));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee"), Comparator.comparing(String::length)));
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
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) {
|
||||
Comparator<CharSequence> comparator1 = comparator.reversed();
|
||||
boolean seen = false;
|
||||
String best = null;
|
||||
for (String string : strings) {
|
||||
if (!seen || comparator1.compare(string, best) < 0) {
|
||||
seen = true;
|
||||
best = string;
|
||||
}
|
||||
}
|
||||
return (seen ? Optional.of(best) : Optional.<String>empty()).orElse(null);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList(), Comparator.comparing(CharSequence::length)));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee"), Comparator.comparing(CharSequence::length)));
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
public class Main {
|
||||
public static int test(List<String> strings) {
|
||||
boolean seen = false;
|
||||
int best = 0;
|
||||
for (String string : strings) {
|
||||
int i = string.length();
|
||||
if (!seen || i < best) {
|
||||
seen = true;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
return (seen ? OptionalInt.of(best) : OptionalInt.empty()).orElse(-1);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d")));
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -10,13 +10,13 @@ public class Main {
|
||||
long sum = 0;
|
||||
for (Map.Entry<String, List<String>> e : strings.entrySet()) {
|
||||
if (!e.getKey().isEmpty()) {
|
||||
long l = e.getValue().stream().filter(new Predicate<String>() {
|
||||
long count = e.getValue().stream().filter(new Predicate<String>() {
|
||||
@Override
|
||||
public boolean test(String s) {
|
||||
return e.getKey().equals(s);
|
||||
}
|
||||
}).count();
|
||||
sum += l;
|
||||
sum += count;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
|
||||
+2
-2
@@ -9,8 +9,8 @@ public class Main {
|
||||
long sum = 0;
|
||||
for (Map.Entry<String, List<String>> e : strings.entrySet()) {
|
||||
if (!e.getKey().isEmpty()) {
|
||||
long l = e.getValue().stream().filter(s -> e.getKey().equals(s)).count();
|
||||
sum += l;
|
||||
long count = e.getValue().stream().filter(s -> e.getKey().equals(s)).count();
|
||||
sum += count;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
|
||||
+2
-2
@@ -9,8 +9,8 @@ public class Main {
|
||||
long sum = 0;
|
||||
for (Map.Entry<String, List<String>> s : strings.entrySet()) {
|
||||
if (!s.getKey().isEmpty()) {
|
||||
long l = s.getValue().stream().filter(sx -> s.getKey().equals(sx)).count();
|
||||
sum += l;
|
||||
long count = s.getValue().stream().filter(sx -> s.getKey().equals(sx)).count();
|
||||
sum += count;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Map<Boolean, List<String>> test(List<String> strings) {
|
||||
Map<Boolean, List<String>> map = new HashMap<>();
|
||||
map.put(false, new ArrayList<>());
|
||||
map.put(true, new ArrayList<>());
|
||||
for (String s : strings) {
|
||||
if (!s.isEmpty()) {
|
||||
map.get(s.length() > 1).add(s);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
Map<Boolean, Map<Character, Set<String>>> map = new HashMap<>();
|
||||
map.put(false, new HashMap<>());
|
||||
map.put(true, new HashMap<>());
|
||||
for (String s : strings) {
|
||||
map.get(s.length() > 2).computeIfAbsent(s.charAt(0), k -> new HashSet<>()).add(s);
|
||||
}
|
||||
System.out.println(map);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd"));
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
Map<Boolean, LinkedHashSet<String>> map = new HashMap<>();
|
||||
map.put(false, new LinkedHashSet<>());
|
||||
map.put(true, new LinkedHashSet<>());
|
||||
for (String s : strings) {
|
||||
map.get(s.length() > 2).add(s);
|
||||
}
|
||||
System.out.println(map);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd", "ee", "e", "e"));
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
Map<Boolean, Map<String, Integer>> map = new HashMap<>();
|
||||
map.put(false, new HashMap<>());
|
||||
map.put(true, new HashMap<>());
|
||||
for (String string : strings) {
|
||||
String s = string.trim();
|
||||
if (map.get(s.length() > 2).put(((UnaryOperator<String>) x -> x).apply(s), s.length()) != null) {
|
||||
throw new IllegalStateException("Duplicate key");
|
||||
}
|
||||
}
|
||||
System.out.println(map);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd", "ee", "e", "e"));
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -8,8 +8,8 @@ public class Main {
|
||||
int sum = 0;
|
||||
for (String s : list) {
|
||||
System.out.println(s);
|
||||
int i = s.length();
|
||||
sum += i;
|
||||
int length = s.length();
|
||||
sum += length;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
+2
-2
@@ -9,8 +9,8 @@ public class Main {
|
||||
LongSummaryStatistics stat = new LongSummaryStatistics();
|
||||
for (String s : list) {
|
||||
System.out.println(s);
|
||||
long l = s.length();
|
||||
stat.accept(l);
|
||||
long length = s.length();
|
||||
stat.accept(length);
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
+2
-2
@@ -8,8 +8,8 @@ public class Main {
|
||||
private static IntSummaryStatistics test() {
|
||||
IntSummaryStatistics stat = new IntSummaryStatistics();
|
||||
for (Number[] nums : Arrays.<Number[]>asList(new Integer[]{1, 2, 3})) {
|
||||
int i = (int) nums[0];
|
||||
stat.accept(i);
|
||||
int num = (int) nums[0];
|
||||
stat.accept(num);
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
+3
-3
@@ -6,12 +6,12 @@ import java.util.stream.IntStream;
|
||||
|
||||
public class Main {
|
||||
private static TreeSet<Integer> test() {
|
||||
TreeSet<Integer> collection = new TreeSet<Integer>();
|
||||
TreeSet<Integer> integers = new TreeSet<>();
|
||||
for (int i : new int[]{4, 2, 1}) {
|
||||
Integer integer = i;
|
||||
collection.add(integer);
|
||||
integers.add(integer);
|
||||
}
|
||||
return collection;
|
||||
return integers;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Map<Integer, String> test(List<String> strings) {
|
||||
Map<Integer, String> map = new HashMap<>();
|
||||
for (String str : strings) {
|
||||
if (map.put(str.length(), str) != null) {
|
||||
throw new IllegalStateException("Duplicate key");
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Map<Integer, String> test(List<String> strings) {
|
||||
Map<Integer, String> map = new HashMap<>();
|
||||
for (String s : strings) {
|
||||
if (!s.isEmpty()) {
|
||||
map.merge(s.length(), s, String::concat);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static TreeMap<Integer, String> test(List<String> strings) {
|
||||
TreeMap<Integer, String> map = new TreeMap<>();
|
||||
for (String s1 : strings) {
|
||||
if (!s1.isEmpty()) {
|
||||
map.merge(s1.length(), s1, (s, string) -> s);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Main {
|
||||
public void test(String... list) {
|
||||
System.out.println(Stream.of(list).filter(Objects::nonNull).col<caret>lect(Collectors.averagingDouble(s -> 1.0/s)));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Main().test("a", "bbb", null, "cc", "dd", "eedasfasdfs");
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Main {
|
||||
public void test(String... list) {
|
||||
System.out.println(Stream.of(list).filter(Objects::nonNull).col<caret>lect(Collectors.averagingInt(String::length)));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Main().test("a", "bbb", null, "cc", "dd", "eedasfasdfs");
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static long test(List<String> strings) {
|
||||
return strings.stream().filter(s -> !s.isEmpty()).coll<caret>ect(Collectors.counting());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Optional<String> test(List<String> strings) {
|
||||
return strings.stream().filter(s -> !s.isEmpty()).c<caret>ollect(Collectors.maxBy(Comparator.naturalOrder()));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Main<T> {
|
||||
void test() {
|
||||
Integer totalLength = Stream.of("a", "bb", "ccc").co<caret>llect(Collectors.reducing(0, String::length, Integer::sum));
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.DoubleSummaryStatistics;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static DoubleSummaryStatistics test(List<String> strings) {
|
||||
return strings.stream().filter(Objects::nonNull).colle<caret>ct(Collectors.summarizingDouble(str -> str.length()/2.0));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList(null, null)));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Double test(List<String> strings) {
|
||||
return strings.stream().filter(Objects::nonNull).co<caret>llect(Collectors.summingDouble(String::length));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList(null, null)));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public void test(List<String> list) {
|
||||
System.out.println(list.stream().map(list.size() < 10 ? String::trim : Function.identity()).colle<caret>ct(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> list) {
|
||||
System.out.println(list.stream()
|
||||
.filter(x -> x != null)
|
||||
.flatMap(s -> IntStream.range(0, 10).boxed().filter(Predicate.isEqual(s.length())))
|
||||
.co<caret>llect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbbb", "cccccccccc", "dd", ""));
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.SplittableRandom;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
int n1 = Stream.generate(() -> 500).limit(100).r<caret>educe(0, new SplittableRandom(1)::nextInt, Integer::sum);
|
||||
System.out.println(n1);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Map<Integer, List<String>> test(List<String> strings) {
|
||||
return strings.stream().col<caret>lect(Collectors.groupingBy(str -> str.length()));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee")));
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Map<Integer, List<String>> test(List<String> strings, int k) {
|
||||
return strings.stream().col<caret>lect(Collectors.groupingBy(String::length));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee")));
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
private static TreeMap<Integer, LinkedHashSet<String>> getMap(List<String> strings) {
|
||||
return strings.stream().coll<caret>ect(
|
||||
Collectors.groupingBy(String::length, () -> new TreeMap<>(Comparator.reverseOrder()), Collectors.toCollection(LinkedHashSet::new)));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(getMap(Arrays.asList("a", "bbb", "cccc", "dddd", "ee", "e")));
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
System.out.println(strings.stream().coll<caret>ect(Collectors.groupingBy(String::length, Collectors.groupingBy(s -> s.charAt(0), Collectors.toSet()))));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd"));
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
private static TreeMap<Integer, List<Integer>> getMap(List<String> strings) {
|
||||
return strings.stream().colle<caret>ct(
|
||||
Collectors.groupingBy(String::length, () -> new TreeMap<>(Comparator.reverseOrder()),
|
||||
Collectors.mapping(String::length, Collectors.mapping(len -> len*2, Collectors.toList()))));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(getMap(Arrays.asList("a", "bbb", "cccc", "dddd", "ee", "e")));
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
System.out.println(strings.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.co<caret>llect(Collectors.groupingBy(String::length, Collectors.summarizingDouble(String::length))));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd"));
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
System.out.println(strings.stream().co<caret>llect(Collectors.groupingBy(String::length, Collectors.toMap(s -> s.charAt(0), Function.identity()))));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd"));
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
System.out.println(strings.stream().filter(Objects::nonNull).col<caret>lect(Collectors.groupingBy(String::length, Collectors.toSet())));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd"));
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
private static void getMap(List<String> strings) {
|
||||
System.out.println(strings.stream().co<caret>llect(Collectors.mapping(String::length, Collectors.mapping(len -> len*2, Collectors.toList()))));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
getMap(Arrays.asList("a", "bbb", "cccc", "dddd", "ee", "e"));
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public static String test(List<String> strings) {
|
||||
return strings.stream().m<caret>ax(Comparator.comparing(String::length)).orElse(null);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee")));
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public static double test(List<String> strings) {
|
||||
return strings.stream().mapToDouble(String::length).m<caret>ax().orElse(-1);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d")));
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public static String test(List<String> strings, Comparator<String> cmp) {
|
||||
return strings.stream().m<caret>in(cmp).orElse(null);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList(), Comparator.comparing(String::length)));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee"), Comparator.comparing(String::length)));
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
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);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList(), Comparator.comparing(CharSequence::length)));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee"), Comparator.comparing(CharSequence::length)));
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public static int test(List<String> strings) {
|
||||
return strings.stream().mapToInt(String::length).mi<caret>n().orElse(-1);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d")));
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Map<Boolean, List<String>> test(List<String> strings) {
|
||||
return strings.stream().filter(s -> !s.isEmpty()).co<caret>llect(Collectors.partitioningBy(s -> s.length() > 1));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
System.out.println(strings.stream().c<caret>ollect(Collectors.partitioningBy((String s) -> s.length() > 2, Collectors.groupingBy(s -> s.charAt(0), Collectors.toSet()))));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd"));
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
System.out.println(strings.stream().co<caret>llect(Collectors.partitioningBy(s -> s.length() > 2, Collectors.toCollection(LinkedHashSet::new))));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd", "ee", "e", "e"));
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
System.out.println(strings.stream().map(x -> x.trim()).colle<caret>ct(Collectors.partitioningBy(s -> s.length() > 2,
|
||||
Collectors.toMap(s -> ((UnaryOperator<String>) x -> x).apply(s), String::length))));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(Arrays.asList("a", "bbb", "cccc", "dddd", "ee", "e", "e"));
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Map<Integer, String> test(List<String> strings) {
|
||||
return strings.stream()
|
||||
.co<caret>llect(Collectors.toMap(String::length, str -> str));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Map<Integer, String> test(List<String> strings) {
|
||||
return strings.stream().filter(s -> !s.isEmpty())
|
||||
.coll<caret>ect(Collectors.toMap(String::length, Function.identity(), String::concat));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace Stream API chain with loop" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static TreeMap<Integer, String> test(List<String> strings) {
|
||||
return strings.stream().filter(s -> !s.isEmpty())
|
||||
.col<caret>lect(Collectors.toMap(String::length, s -> s, (s, string) -> s, TreeMap::new));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(test(Arrays.asList()));
|
||||
System.out.println(test(Arrays.asList("a", "bbb", "cc", "d", "eee", "")));
|
||||
}
|
||||
}
|
||||
@@ -110,6 +110,7 @@ public interface CommonClassNames {
|
||||
@NonNls String JAVA_UTIL_STREAM_DOUBLE_STREAM = "java.util.stream.DoubleStream";
|
||||
@NonNls String JAVA_UTIL_STREAM_COLLECTORS = "java.util.stream.Collectors";
|
||||
@NonNls String JAVA_UTIL_FUNCTION_PREDICATE = "java.util.function.Predicate";
|
||||
@NonNls String JAVA_UTIL_FUNCTION_FUNCTION = "java.util.function.Function";
|
||||
|
||||
@NonNls String JAVA_LANG_INVOKE_MH_POLYMORPHIC = "java.lang.invoke.MethodHandle.PolymorphicSignature";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user