All Downloads are FREE. Search and download functionalities are using the official Maven repository.

category.java.performance.xml Maven / Gradle / Ivy

There is a newer version: 7.7.0
Show newest version
<?xml version="1.0"?>

<ruleset name="Performance"
    xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">

    <description>
Rules that flag suboptimal code.
    </description>

    <rule name="AddEmptyString"
          language="java"
          since="4.0"
          message="Do not add empty strings"
          class="net.sourceforge.pmd.lang.java.rule.performance.AddEmptyStringRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#addemptystring">
        <description>
The conversion of literals to strings by concatenating them with empty strings is inefficient.
It is much better to use one of the type-specific `toString()` methods instead or `String.valueOf()`.
        </description>
        <priority>3</priority>
        <example>
<![CDATA[
String s = "" + 123;                // inefficient
String t = Integer.toString(456);   // preferred approach
]]>
        </example>
    </rule>

    <rule name="AppendCharacterWithChar"
          language="java"
          since="3.5"
          message="Avoid appending characters as strings in StringBuffer.append."
          class="net.sourceforge.pmd.lang.java.rule.performance.AppendCharacterWithCharRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#appendcharacterwithchar">
        <description>
Avoid concatenating characters as strings in StringBuffer/StringBuilder.append methods.
        </description>
        <priority>3</priority>
        <example>
<![CDATA[
StringBuffer sb = new StringBuffer();
sb.append("a");     // avoid this

StringBuffer sb = new StringBuffer();
sb.append('a');     // use this instead
]]>
        </example>
    </rule>

    <rule name="AvoidArrayLoops"
          language="java"
          since="3.5"
          message="Arrays.copyOf or System.arraycopy are more efficient"
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#avoidarrayloops">
        <description>
Instead of manually copying data between two arrays, use the more efficient `Arrays.copyOf`
or `System.arraycopy` method instead.

To copy only part of the array, use `Arrays.copyOfRange` or `System.arraycopy`.

If you want to copy/move elements inside the _same_ array (e.g. shift the elements), use `System.arraycopy`.
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value>
<![CDATA[
//(ForStatement[ForUpdate//(UnaryExpression[@Operator=('++','--')] | AssignmentExpression[@Operator = ('+=', '-=')][NumericLiteral[@Image = '1']])]
 | WhileStatement | DoStatement)
    [not(.//ContinueStatement)]
    [not(.//BreakStatement)]
    [not(.//ThrowStatement)]
    [not(.//ReturnStatement)]
    [count(Block//AssignmentExpression[@Operator='=']
                                      (: no nested arrays or method calls as array index :)
                                      [count(ArrayAccess[not(.//ArrayAccess)]
                                                        [not(.//MethodCall)])=2]
                                      (: array access indexes must be same (excluding constants) :)
                                      [deep-equal(
                                        sort(distinct-values(ArrayAccess[1]/(VariableAccess[2]|InfixExpression//VariableAccess)
                                            (: don't consider array length accesses :)
                                            [not(parent::FieldAccess[@Name='length'])]
                                            [
                                               (: exclude referenced constants :)
                                               not(@Name = (ancestor::MethodDeclaration|//FieldDeclaration)//VariableDeclarator[NumericLiteral][not(../../../parent::ForInit)]/VariableDeclaratorId/@Name)
                                               or
                                               (: include loop variable :)
                                               @Name = ancestor::ForStatement/ForInit/LocalVariableDeclaration/VariableDeclarator/VariableDeclaratorId/@Name
                                            ]
                                            /@Name)),
                                        sort(distinct-values(ArrayAccess[2]/(VariableAccess[2]|InfixExpression//VariableAccess)
                                            (: don't consider array length accesses :)
                                            [not(parent::FieldAccess[@Name='length'])]
                                            [
                                               (: exclude referenced constants :)
                                               not(@Name = (ancestor::MethodDeclaration|//FieldDeclaration)//VariableDeclarator[NumericLiteral][not(../../../parent::ForInit)]/VariableDeclaratorId/@Name)
                                               or
                                               (: include loop variable :)
                                               @Name = ancestor::ForStatement/ForInit/LocalVariableDeclaration/VariableDeclarator/VariableDeclaratorId/@Name
                                            ]
                                            /@Name))
                                      )]
     )=1]
]]>
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
class Scratch {
    void copy_a_to_b() {
        int[] a = new int[10];
        int[] b = new int[10];
        for (int i = 0; i < a.length; i++) {
            b[i] = a[i];
        }
        // equivalent
        b = Arrays.copyOf(a, a.length);
        // equivalent
        System.arraycopy(a, 0, b, 0, a.length);

        int[] c = new int[10];
        // this will not trigger the rule
        for (int i = 0; i < c.length; i++) {
            b[i] = a[c[i]];
        }
    }
}
]]>
        </example>
        <example>
<![CDATA[
class Scratch {
    void shift_left(int[] a) {
        for (int i = 0; i < a.length - 1; i++) {
            a[i] = a[i + 1];
        }
        // equivalent
        System.arraycopy(a, 1, a, 0, a.length - 1);
    }
    void shift_right(int[] a) {
        for (int i = a.length - 1; i > 0; i--) {
            a[i] = a[i - 1];
        }
        // equivalent
        System.arraycopy(a, 0, a, 1, a.length - 1);
    }
}
]]>
        </example>
    </rule>

    <rule name="AvoidCalendarDateCreation"
          since="6.25.0"
          language="java"
          message="A Calendar is used to get the current time, this is expensive."
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          typeResolution="true"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#avoidcalendardatecreation">
        <description>
Problem: `java.util.Calendar` is a heavyweight object and expensive to create. It should only be used, if
calendar calculations are needed.

Solution: Use `new Date()`, Java 8+ `java.time.LocalDateTime.now()` or `ZonedDateTime.now()`.
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value><![CDATA[
//MethodCall[pmd-java:matchesSig("java.util.Calendar#getTime()") or pmd-java:matchesSig("java.util.Calendar#getTimeInMillis()")]
  [*[1][local-name() = ('MethodCall', 'ConstructorCall')]
                               [pmd-java:matchesSig("java.util.Calendar#getInstance()")
                             or pmd-java:matchesSig("java.util.GregorianCalendar#getInstance()")
                             or pmd-java:matchesSig("java.util.GregorianCalendar#new()")]
  ]
|
//MethodCall[pmd-java:matchesSig("java.util.Calendar#getTime()") or pmd-java:matchesSig("java.util.Calendar#getTimeInMillis()")]
   [*[1][local-name() = 'VariableAccess']]
  (: ignore if .set* or .add or .clear or .roll is called on the variable :)
  [not(VariableAccess/@Name = ancestor::Block//MethodCall[starts-with(@MethodName, "set") or @MethodName = ("add", "clear", "roll")]/VariableAccess/@Name)]
  (: variable must be initialized with getInstance :)
  [VariableAccess/@Name = ancestor::Block//LocalVariableDeclaration/VariableDeclarator[
     (MethodCall | ConstructorCall)
      [pmd-java:matchesSig("java.util.Calendar#getInstance()")
       or pmd-java:matchesSig("java.util.GregorianCalendar#getInstance()")
       or pmd-java:matchesSig("java.util.GregorianCalendar#new()")]
  ]/VariableDeclaratorId/@Name]
|
//ConstructorCall[pmd-java:typeIs("org.joda.time.DateTime") or pmd-java:typeIs("org.joda.time.LocalDateTime")]
  [ArgumentList[(MethodCall | ConstructorCall)
       [pmd-java:matchesSig("java.util.Calendar#getInstance()")
     or pmd-java:matchesSig("java.util.GregorianCalendar#getInstance()")
     or pmd-java:matchesSig("java.util.GregorianCalendar#new()")]]
  ]

                ]]></value>
            </property>
        </properties>
        <example>
            <![CDATA[
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.Date;

public class DateStuff {
    private Date bad1() {
        return Calendar.getInstance().getTime(); // now
    }
    private Date good1a() {
        return new Date(); // now
    }
    private LocalDateTime good1b() {
        return LocalDateTime.now();
    }
    private long bad2() {
        return Calendar.getInstance().getTimeInMillis();
    }
    private long good2() {
        return System.currentTimeMillis();
    }
}
            ]]>
        </example>
    </rule>

    <rule name="AvoidFileStream"
          since="6.0.0"
          message="Avoid instantiating FileInputStream, FileOutputStream, FileReader, or FileWriter"
          language="java"
          minimumLanguageVersion="1.7"
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#avoidfilestream">
        <description>
The FileInputStream and FileOutputStream classes contains a finalizer method which will cause garbage
collection pauses.
See [JDK-8080225](https://bugs.openjdk.java.net/browse/JDK-8080225) for details.

The FileReader and FileWriter constructors instantiate FileInputStream and FileOutputStream,
again causing garbage collection issues while finalizer methods are called.

* Use `Files.newInputStream(Paths.get(fileName))` instead of `new FileInputStream(fileName)`.
* Use `Files.newOutputStream(Paths.get(fileName))` instead of `new FileOutputStream(fileName)`.
* Use `Files.newBufferedReader(Paths.get(fileName))` instead of `new FileReader(fileName)`.
* Use `Files.newBufferedWriter(Paths.get(fileName))` instead of `new FileWriter(fileName)`.

Please note, that the `java.nio` API does not throw a `FileNotFoundException` anymore, instead
it throws a `NoSuchFileException`. If your code dealt explicitly with a `FileNotFoundException`,
then this needs to be adjusted. Both exceptions are subclasses of `IOException`, so catching
that one covers both.
        </description>
        <priority>1</priority>
        <properties>
            <property name="xpath">
                <value>
<![CDATA[
//ConstructorCall/ClassOrInterfaceType[
       pmd-java:typeIs('java.io.FileInputStream')
    or pmd-java:typeIs('java.io.FileOutputStream')
    or pmd-java:typeIs('java.io.FileReader')
    or pmd-java:typeIs('java.io.FileWriter')
  ]
]]>
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
    // these instantiations cause garbage collection pauses, even if properly closed

    FileInputStream fis = new FileInputStream(fileName);
    FileOutputStream fos = new FileOutputStream(fileName);
    FileReader fr = new FileReader(fileName);
    FileWriter fw = new FileWriter(fileName);

    // the following instantiations help prevent Garbage Collection pauses, no finalization

    try(InputStream is = Files.newInputStream(Paths.get(fileName))) {
    }
    try(OutputStream os = Files.newOutputStream(Paths.get(fileName))) {
    }
    try(BufferedReader br = Files.newBufferedReader(Paths.get(fileName), StandardCharsets.UTF_8)) {
    }
    try(BufferedWriter wr = Files.newBufferedWriter(Paths.get(fileName), StandardCharsets.UTF_8)) {
    }
]]>
        </example>
    </rule>

    <rule name="AvoidInstantiatingObjectsInLoops"
          language="java"
          since="2.2"
          message="Avoid instantiating new objects inside loops"
          class="net.sourceforge.pmd.lang.java.rule.performance.AvoidInstantiatingObjectsInLoopsRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#avoidinstantiatingobjectsinloops">
        <description>
New objects created within loops should be checked to see if they can created outside them and reused.
        </description>
        <priority>3</priority>
        <example>
<![CDATA[
public class Something {
    public static void main( String as[] ) {
        for (int i = 0; i < 10; i++) {
            Foo f = new Foo(); // Avoid this whenever you can it's really expensive
        }
    }
}
]]>
        </example>
    </rule>

    <rule name="BigIntegerInstantiation"
          language="java"
          since="3.9"
          message="Don''t create instances of already existing BigInteger and BigDecimal (ZERO, ONE, TEN)"
          class="net.sourceforge.pmd.lang.java.rule.performance.BigIntegerInstantiationRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#bigintegerinstantiation">
        <description>
Don't create instances of already existing BigInteger (`BigInteger.ZERO`, `BigInteger.ONE`),
for Java 1.5 onwards, BigInteger.TEN and BigDecimal (`BigDecimal.ZERO`, `BigDecimal.ONE`, `BigDecimal.TEN`) and
for Java 9 onwards `BigInteger.TWO`.
        </description>
        <priority>3</priority>
        <example>
<![CDATA[
BigInteger bi1 = new BigInteger("1");    // reference BigInteger.ONE instead
BigInteger bi2 = new BigInteger("0");    // reference BigInteger.ZERO instead
BigInteger bi3;
bi3 = new BigInteger("0");               // reference BigInteger.ZERO instead

BigDecimal bd1 = new BigDecimal(0);      // reference BigDecimal.ZERO instead
BigDecimal bd2 = new BigDecimal("0.") ;  // reference BigDecimal.ZERO instead
BigDecimal bd3 = new BigDecimal(10);     // reference BigDecimal.TEN instead
]]>
        </example>
    </rule>

    <rule name="ConsecutiveAppendsShouldReuse"
          language="java"
          since="5.1"
          message="StringBuffer (or StringBuilder).append is called consecutively without reusing the target variable."
          class="net.sourceforge.pmd.lang.java.rule.performance.ConsecutiveAppendsShouldReuseRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#consecutiveappendsshouldreuse">
        <description>
Consecutive calls to StringBuffer/StringBuilder .append should be chained, reusing the target object. This can improve the performance
by producing a smaller bytecode, reducing overhead and improving inlining. A complete analysis can be found [here](https://github.com/pmd/pmd/issues/202#issuecomment-274349067)
        </description>
        <priority>3</priority>
        <example>
<![CDATA[
String foo = " ";

StringBuffer buf = new StringBuffer();
buf.append("Hello"); // poor
buf.append(foo);
buf.append("World");

StringBuffer buf = new StringBuffer();
buf.append("Hello").append(foo).append("World"); // good
]]>
        </example>
    </rule>

    <rule name="ConsecutiveLiteralAppends"
          language="java"
          since="3.5"
          message="StringBuffer (or StringBuilder).append is called {0} consecutive times with literals. Use a single append with a single combined String."
          class="net.sourceforge.pmd.lang.java.rule.performance.ConsecutiveLiteralAppendsRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#consecutiveliteralappends">
        <description>
Consecutively calling StringBuffer/StringBuilder.append(...) with literals should be avoided.
Since the literals are constants, they can already be combined into a single String literal and this String
can be appended in a single method call.
        </description>
        <priority>3</priority>
        <example>
<![CDATA[
StringBuilder buf = new StringBuilder();
buf.append("Hello").append(" ").append("World");    // poor
buf.append("Hello World");                          // good

buf.append('h').append('e').append('l').append('l').append('o'); // poor
buf.append("hello");                                             // good

buf.append(1).append('m');  // poor
buf.append("1m");           // good
]]>
        </example>
    </rule>

    <rule name="InefficientEmptyStringCheck"
          language="java"
          since="3.6"
	        message="String.trim().length() == 0 / String.trim().isEmpty() is an inefficient way to validate a blank String."
          class="net.sourceforge.pmd.lang.java.rule.performance.InefficientEmptyStringCheckRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#inefficientemptystringcheck">
        <description>
<![CDATA[
String.trim().length() == 0 (or String.trim().isEmpty() for the same reason) is an inefficient
way to check if a String is really blank, as it creates a new String object just to check its size.
Consider creating a static function that loops through a string, checking Character.isWhitespace()
on each character and returning false if a non-whitespace character is found. A Smarter code to
check for an empty string would be:

```java
private boolean checkTrimEmpty(String str) {
    for(int i = 0; i < str.length(); i++) {
        if(!Character.isWhitespace(str.charAt(i))) {
            return false;
        }
    }
    return true;
}
```

You can refer to Apache's StringUtils#isBlank (in commons-lang),
Spring's StringUtils#hasText (in the Spring framework) or Google's
CharMatcher#whitespace (in Guava) for existing implementations (some might
include the check for != null).
]]>
        </description>
        <priority>3</priority>
        <example>
<![CDATA[
public void bar(String string) {
    if (string != null && string.trim().length() > 0) {
        doSomething();
    }
}
]]>
        </example>
    </rule>

    <rule name="InefficientStringBuffering"
          language="java"
          since="3.4"
          message="Avoid concatenating nonliterals in a StringBuffer/StringBuilder constructor or append()."
          class="net.sourceforge.pmd.lang.java.rule.performance.InefficientStringBufferingRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#inefficientstringbuffering">
        <description>
Avoid concatenating non-literals in a StringBuffer constructor or append() since intermediate buffers will
need to be be created and destroyed by the JVM.
        </description>
        <priority>3</priority>
        <example>
<![CDATA[
// Avoid this, two buffers are actually being created here
StringBuffer sb = new StringBuffer("tmp = "+System.getProperty("java.io.tmpdir"));

// do this instead
StringBuffer sb = new StringBuffer("tmp = ");
sb.append(System.getProperty("java.io.tmpdir"));
]]>
        </example>
    </rule>

    <rule name="InsufficientStringBufferDeclaration"
          language="java"
          since="3.6"
          message="{0} has been initialized with size {1}, but has at least {2} characters appended."
          class="net.sourceforge.pmd.lang.java.rule.performance.InsufficientStringBufferDeclarationRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#insufficientstringbufferdeclaration">
        <description>
Failing to pre-size a StringBuffer or StringBuilder properly could cause it to re-size many times
during runtime. This rule attempts to determine the total number the characters that are actually
passed into StringBuffer.append(), but represents a best guess "worst case" scenario. An empty
StringBuffer/StringBuilder constructor initializes the object to 16 characters. This default
is assumed if the length of the constructor can not be determined.
        </description>
        <priority>3</priority>
        <example>
<![CDATA[
StringBuilder bad = new StringBuilder();
bad.append("This is a long string that will exceed the default 16 characters");

StringBuilder good = new StringBuilder(41);
good.append("This is a long string, which is pre-sized");
]]>
        </example>
    </rule>

    <rule name="OptimizableToArrayCall"
          language="java"
          since="1.8"
          minimumLanguageVersion="1.6"
          message="This call to Collection.toArray() may be optimizable"
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#optimizabletoarraycall">
        <description>
Calls to a collection's `toArray(E[])` method should specify a target array of zero size. This allows the JVM
to optimize the memory allocation and copying as much as possible.

Previous versions of this rule (pre PMD 6.0.0) suggested the opposite, but current JVM implementations
perform always better, when they have full control over the target array. And allocation an array via
reflection is nowadays as fast as the direct allocation.

See also [Arrays of Wisdom of the Ancients](https://shipilev.net/blog/2016/arrays-wisdom-ancients/)

Note: If you don't need an array of the correct type, then the simple `toArray()` method without an array
is faster, but returns only an array of type `Object[]`.
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value>
<![CDATA[
//MethodCall[pmd-java:matchesSig("java.util.Collection#toArray(_)")]
    [ArgumentList/ArrayAllocation/ArrayType/ArrayDimensions/ArrayDimExpr[not(NumericLiteral[@Image="0"])]]
]]>
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
List<Foo> foos = getFoos();

// much better; this one allows the jvm to allocate an array of the correct size and effectively skip
// the zeroing, since each array element will be overridden anyways
Foo[] fooArray = foos.toArray(new Foo[0]);

// inefficient, the array needs to be zeroed out by the jvm before it is handed over to the toArray method
Foo[] fooArray = foos.toArray(new Foo[foos.size()]);
]]>
        </example>
    </rule>

    <rule name="RedundantFieldInitializer"
          language="java"
          since="5.0"
          message="Avoid using redundant field initializer for ''${variableName}''"
          class="net.sourceforge.pmd.lang.java.rule.performance.RedundantFieldInitializerRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#redundantfieldinitializer">
        <description>
Java will initialize fields with known default values so any explicit initialization of those same defaults
is redundant and results in a larger class file (approximately three additional bytecode instructions per field).
        </description>
        <priority>3</priority>
        <example>
<![CDATA[
public class C {
    boolean b   = false;    // examples of redundant initializers
    byte by     = 0;
    short s     = 0;
    char c      = 0;
    int i       = 0;
    long l      = 0;

    float f     = .0f;    // all possible float literals
    doable d    = 0d;     // all possible double literals
    Object o    = null;

    MyClass mca[] = null;
    int i1 = 0, ia1[] = null;

    class Nested {
        boolean b = false;
    }
}
]]>
        </example>
    </rule>

    <rule name="StringInstantiation"
          language="java"
          since="1.0"
          message="Avoid instantiating String objects; this is usually unnecessary."
          class="net.sourceforge.pmd.lang.java.rule.performance.StringInstantiationRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#stringinstantiation">
        <description>
Avoid instantiating String objects; this is usually unnecessary since they are immutable and can be safely shared.
        </description>
        <priority>2</priority>
        <example>
<![CDATA[
private String bar = new String("bar"); // just do a String bar = "bar";
]]>
        </example>
    </rule>

    <rule name="StringToString"
          language="java"
          since="1.0"
          message="Avoid calling toString() on String objects; this is unnecessary."
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#stringtostring">
        <description>
Avoid calling toString() on objects already known to be string instances; this is unnecessary.
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value>
                    //MethodCall[pmd-java:matchesSig("java.lang.String#toString()")]
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
private String baz() {
    String bar = "howdy";
    return bar.toString();
}
]]>
        </example>
    </rule>

    <rule name="TooFewBranchesForASwitchStatement"
          language="java"
          since="4.2"
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          message="A switch with less than three branches is inefficient, use a 'if statement' instead."
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#toofewbranchesforaswitchstatement">
        <description>
Switch statements are intended to be used to support complex branching behaviour. Using a switch for only a few
cases is ill-advised, since switches are not as easy to understand as if-else statements. In these cases use the
if-else statement to increase code readability.
        </description>
        <priority>3</priority>
        <properties>
            <property name="minimumNumberCaseForASwitch" type="Integer" description="Minimum number of branches for a switch" min="1" max="100" value="3"/>
            <property name="xpath">
                <value>
<![CDATA[
//SwitchStatement[ (count(*) - 1) < $minimumNumberCaseForASwitch ]
]]>
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
// With a minimumNumberCaseForASwitch of 3
public class Foo {
    public void bar() {
        switch (condition) {
            case ONE:
                instruction;
                break;
            default:
                break; // not enough for a 'switch' stmt, a simple 'if' stmt would have been more appropriate
        }
    }
}
]]>
        </example>
    </rule>

    <rule name="UseArrayListInsteadOfVector"
          language="java"
          since="3.0"
          message="Use ArrayList instead of Vector"
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#usearraylistinsteadofvector">
        <description>
ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required.
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value>
<![CDATA[
//ConstructorCall/ClassOrInterfaceType[pmd-java:typeIsExactly('java.util.Vector') or pmd-java:typeIsExactly('Vector')]
]]>
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
import java.util.*;
public class SimpleTest extends TestCase {
    public void testX() {
    Collection c1 = new Vector();
    Collection c2 = new ArrayList();    // achieves the same with much better performance
    }
}
]]>
        </example>
    </rule>

    <rule name="UseArraysAsList"
          language="java"
          since="3.5"
          message="Use asList instead of tight loops"
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#usearraysaslist">
        <description>
<![CDATA[
The `java.util.Arrays` class has a `asList()` method that should be used when you want to create a new List from
an array of objects. It is faster than executing a loop to copy all the elements of the array one by one.

Note that the result of `Arrays.asList()` is backed by the specified array,
changes in the returned list will result in the array to be modified.
For that reason, it is not possible to add new elements to the returned list of `Arrays.asList()`
(UnsupportedOperationException).
You must use `new ArrayList<>(Arrays.asList(...))` if that is inconvenient for you (e.g. because of concurrent access).
]]>
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value>
<![CDATA[
//ForStatement
  [ForInit
    [LocalVariableDeclaration
      [PrimitiveType[@Kind = 'int']]
      [VariableDeclarator[NumericLiteral[@IntLiteral][@Image = '0']]]
    ]
  ]
  [*[2]//FieldAccess[@Name = 'length']/VariableAccess[pmd-java:typeIs("java.lang.Object[]")]]
  /*[last()]/ExpressionStatement/
    MethodCall
      [pmd-java:matchesSig('java.util.Collection#add(_)')]
      [ArgumentList/ArrayAccess
        [VariableAccess[@Name = ancestor::ForStatement/ForInit/LocalVariableDeclaration/VariableDeclarator/VariableDeclaratorId/@Name]]
      ]
|
//ForeachStatement
  [VariableAccess[pmd-java:typeIs("java.lang.Object[]")]]
  /*[last()]/ExpressionStatement/MethodCall
      [pmd-java:matchesSig('java.util.Collection#add(_)')]
      [ArgumentList
        [VariableAccess[@Name = ancestor::ForeachStatement/LocalVariableDeclaration/VariableDeclarator/VariableDeclaratorId/@Name]]
      ]
]]>
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
public class Test {
    public void foo(Integer[] ints) {
        // could just use Arrays.asList(ints)
        List<Integer> l = new ArrayList<>(100);
        for (int i = 0; i < ints.length; i++) {
            l.add(ints[i]);
        }

        List<Integer> anotherList = new ArrayList<>();
        for (int i = 0; i < ints.length; i++) {
            anotherList.add(ints[i].toString()); // won't trigger the rule
        }
    }
}
]]>
        </example>
    </rule>

    <rule name="UseIndexOfChar"
          language="java"
          since="3.5"
          message="String.indexOf(char) is faster than String.indexOf(String)."
          class="net.sourceforge.pmd.lang.java.rule.performance.UseIndexOfCharRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#useindexofchar">
        <description>
Use String.indexOf(char) when checking for the index of a single character; it executes faster.
        </description>
        <priority>3</priority>
        <example>
<![CDATA[
String s = "hello world";
// avoid this
if (s.indexOf("d") {}
// instead do this
if (s.indexOf('d') {}
]]>
        </example>
    </rule>

    <rule name="UseIOStreamsWithApacheCommonsFileItem"
          since="6.25.0"
          language="java"
          message="Avoid memory intensive FileItem.get() or FileItem.getString()"
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          typeResolution="true"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#useiostreamswithapachecommonsfileitem">
        <description>
Problem: Use of [FileItem.get()](https://commons.apache.org/proper/commons-fileupload/apidocs/org/apache/commons/fileupload/FileItem.html#get--)
and [FileItem.getString()](https://commons.apache.org/proper/commons-fileupload/apidocs/org/apache/commons/fileupload/FileItem.html#getString--)
could exhaust memory since they load the entire file into memory.

Solution: Use [FileItem.getInputStream()](https://commons.apache.org/proper/commons-fileupload/apidocs/org/apache/commons/fileupload/FileItem.html#getInputStream--)
and buffering.
        </description>
        <priority>3</priority>
        <properties>
            <property name="version" value="2.0"/>
            <property name="xpath">
                <value>
                    <![CDATA[
//MethodCall
    [@MethodName = 'get' or @MethodName = 'getString']
    [*[pmd-java:typeIs('org.apache.commons.fileupload.FileItem')]]
                    ]]>
                </value>
            </property>
        </properties>
        <example>
            <![CDATA[
import org.apache.commons.fileupload.FileItem;

public class FileStuff {
   private String bad(FileItem fileItem) {
        return fileItem.getString();
   }

   private InputStream good(FileItem fileItem) {
        return fileItem.getInputStream();
   }
}
            ]]>
        </example>
    </rule>

    <rule name="UselessStringValueOf"
          language="java"
          since="3.8"
          message="No need to call String.valueOf to append to a string."
          class="net.sourceforge.pmd.lang.java.rule.performance.UselessStringValueOfRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#uselessstringvalueof">
        <description>
No need to call String.valueOf to append to a string; just use the valueOf() argument directly.
        </description>
        <priority>3</priority>
        <example>
<![CDATA[
public String convert(int i) {
    String s;
    s = "a" + String.valueOf(i);    // not required
    s = "a" + i;                    // preferred approach
    return s;
}
]]>
        </example>
    </rule>

    <rule name="UseStringBufferForStringAppends"
          language="java"
          since="3.1"
          message="Prefer StringBuilder (non-synchronized) or StringBuffer (synchronized) over += for concatenating strings"
          class="net.sourceforge.pmd.lang.java.rule.performance.UseStringBufferForStringAppendsRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#usestringbufferforstringappends">
        <description>
The use of the '+=' operator for appending strings causes the JVM to create and use an internal StringBuffer.
If a non-trivial number of these concatenations are being used then the explicit use of a StringBuilder or
threadsafe StringBuffer is recommended to avoid this.
        </description>
        <priority>3</priority>
        <example>
<![CDATA[
public class Foo {
    String inefficientConcatenation() {
        String result = "";
        for (int i = 0; i < 10; i++) {
            // warning: this concatenation will create one new StringBuilder per iteration
            result += getStringFromSomeWhere(i);
        }
        return result;
    }

    String efficientConcatenation() {
        // better would be to use one StringBuilder for the entire loop
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            result.append(getStringFromSomeWhere(i));
        }
        return result.toString();
    }
}
]]>
        </example>
    </rule>

    <rule name="UseStringBufferLength"
          language="java"
          since="3.4"
          message="This is an inefficient use of CharSequence.toString; call CharSequence.length instead."
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#usestringbufferlength">
        <description>
Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toString().equals("")
or StringBuffer.toString().length() == ...
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value><![CDATA[
//MethodCall[pmd-java:matchesSig('_#length()')
    and MethodCall[pmd-java:matchesSig('java.lang.CharSequence#toString()')]]
|
(: finds sb.toString().equals(someVar) where var is a final variable initialized with literal "" :)
//MethodCall[pmd-java:matchesSig('_#equals(_)')
  and MethodCall[pmd-java:matchesSig('java.lang.AbstractStringBuilder#toString()')]
  and ArgumentList/VariableAccess[@Name = //VariableDeclarator[StringLiteral[@Image='""']]
                                            /VariableDeclaratorId[pmd-java:modifiers() = 'final']/@Name]]
]]></value>
            </property>
        </properties>
        <example>
<![CDATA[
StringBuffer sb = new StringBuffer();

if (sb.toString().equals("")) {}        // inefficient

if (sb.length() == 0) {}                // preferred
]]>
        </example>
    </rule>


    <!--
    other optimization/performance should be like avoiding
    "" + int
    or "" + (int) i
    and String.valueOf(int)

    and using Integer.toString(int)

    IntegerToStringShouldBeUsed
    LongToStringShouldBeUsed
    BooleanToStringShouldBeUsed
    -->

</ruleset>




© 2015 - 2024 Weber Informatics LLC | Privacy Policy