# Performance

Rules that flag suboptimal code.
Table of Contents

## AddEmptyString

Since: PMD 4.0

Priority: Medium (3)

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()`.

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.AddEmptyStringRule

Example(s):

    String s = "" + 123;                // inefficient
    String t = Integer.toString(456);   // preferred approach

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/AddEmptyString" />

## AppendCharacterWithChar

Since: PMD 3.5

Priority: Medium (3)

Avoid concatenating characters as strings in StringBuffer/StringBuilder.append methods.

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.AppendCharacterWithCharRule

Example(s):

    StringBuffer sb = new StringBuffer();
    sb.append("a");     // avoid this

    StringBuffer sb = new StringBuffer();
    sb.append('a');     // use this instead

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/AppendCharacterWithChar" />

## AvoidArrayLoops

Since: PMD 3.5

Priority: Medium (3)

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`.

This rule is defined by the following XPath expression:

    //(ForStatement[ForUpdate//(UnaryExpression[@Operator=('++','--')] | AssignmentExpression[@Operator = ('+=', '-=')][NumericLiteral[@Image = '1']])]
     | WhileStatement | DoStatement)
        [not(.//ContinueStatement)]
        [not(.//BreakStatement[not(parent::SwitchFallthroughBranch)])]
        [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)]/VariableId/@Name)
                                                   or
                                                   (: include loop variable :)
                                                   @Name = ancestor::ForStatement/ForInit/LocalVariableDeclaration/VariableDeclarator/VariableId/@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)]/VariableId/@Name)
                                                   or
                                                   (: include loop variable :)
                                                   @Name = ancestor::ForStatement/ForInit/LocalVariableDeclaration/VariableDeclarator/VariableId/@Name
                                                ]
                                                /@Name))
                                          )]
         )=1]

Example(s):

    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]];
            }
        }
    }

    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);
        }
    }

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/AvoidArrayLoops" />

## AvoidCalendarDateCreation

Since: PMD 6.25.0

Priority: Medium (3)

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()`.

This rule is defined by the following XPath expression:

    //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()")]
      ]/VariableId/@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()")]]
      ]

Example(s):

    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();
        }
    }

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/AvoidCalendarDateCreation" />

## AvoidFileStream

Since: PMD 6.0.0

Priority: High (1)

Minimum Language Version: Java 1.7

The FileInputStream and FileOutputStream classes contains a finalizer method which will cause garbage collection pauses. See 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.

This rule is defined by the following XPath expression:

    //ConstructorCall/ClassType[
           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')
      ]

Example(s):

    // 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)) {
        }

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/AvoidFileStream" />

## AvoidInstantiatingObjectsInLoops

Since: PMD 2.2

Priority: Medium (3)

New objects created within loops should be checked to see if they can created outside them and reused.

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.AvoidInstantiatingObjectsInLoopsRule

Example(s):

    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
            }
        }
    }

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/AvoidInstantiatingObjectsInLoops" />

## BigIntegerInstantiation

Since: PMD 3.9

Priority: Medium (3)

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`.

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.BigIntegerInstantiationRule

Example(s):

    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

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/BigIntegerInstantiation" />

## ConsecutiveAppendsShouldReuse

Since: PMD 5.1

Priority: Medium (3)

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

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.ConsecutiveAppendsShouldReuseRule

Example(s):

    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

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/ConsecutiveAppendsShouldReuse" />

## ConsecutiveLiteralAppends

Since: PMD 3.5

Priority: Medium (3)

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.

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.ConsecutiveLiteralAppendsRule

Example(s):

    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

This rule has the following properties:

Name | Default Value | Description
--- | --- | ---
threshold | 1 | Max consecutive appends

Use this rule with the default properties by just referencing it:

    <rule ref="category/java/performance.xml/ConsecutiveLiteralAppends" />

Use this rule and customize it:

    <rule ref="category/java/performance.xml/ConsecutiveLiteralAppends">
        <properties>
            <property name="threshold" value="1" />
        </properties>
    </rule>

## InefficientEmptyStringCheck

Since: PMD 3.6

Priority: Medium (3)

Checking the length of `string.trim()` or `string.strip()` is an inefficient way to decide if a string is really blank, as it creates a new `String` object just to check its size. As of Java 11 you can use `string.isBlank()` to decide if a string consists only of whitespace, that check is equivalent to `string.strip().isEmpty()`. To get the semantic of `string.trim().isEmpty()`, you can loop through the characters and compare them to 0x20:

    private boolean checkTrimEmpty(String str) {
        return str.chars().allMatch(c -> c <= 0x20);
    }

You can also consider using library functions that include a null check (e.g. Apache’s `StringUtils#isBlank` in commons-lang, Spring’s `StringUtils#hasText` in the Spring framework) or use a different definition of whitespace (e.g. Google’s `CharMatcher#whitespace` in Guava).

Calling `string.strip().isBlank()` is also redundant and should be simplified to `string.isBlank()`.

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.InefficientEmptyStringCheckRule

Example(s):

    public void bar(String string) {
        if (string != null && string.trim().length() > 0) {
            doSomething();
        }
    }

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/InefficientEmptyStringCheck" />

## InefficientStringBuffering

Since: PMD 3.4

Priority: Medium (3)

Avoid concatenating non-literals in a StringBuffer constructor or append() since intermediate buffers will need to be be created and destroyed by the JVM.

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.InefficientStringBufferingRule

Example(s):

    // 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"));

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/InefficientStringBuffering" />

## InsufficientStringBufferDeclaration

Since: PMD 3.6

Priority: Medium (3)

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.

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.InsufficientStringBufferDeclarationRule

Example(s):

    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");

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/InsufficientStringBufferDeclaration" />

## OptimizableToArrayCall

Since: PMD 1.8

Priority: Medium (3)

Minimum Language Version: Java 1.6

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

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[]`.

This rule is defined by the following XPath expression:

    //MethodCall[pmd-java:matchesSig("java.util.Collection#toArray(_)")]
        [ArgumentList/ArrayAllocation/ArrayType/ArrayDimensions/ArrayDimExpr[not(NumericLiteral[@Image="0"])]]

Example(s):

    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()]);

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/OptimizableToArrayCall" />

## RedundantFieldInitializer

Since: PMD 5.0

Priority: Medium (3)

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).

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.RedundantFieldInitializerRule

Example(s):

    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
        double d    = 0d;     // all possible double literals
        Object o    = null;

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

        class Nested {
            boolean b = false;
        }
    }

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/RedundantFieldInitializer" />

## StringInstantiation

Since: PMD 1.0

Priority: Medium High (2)

Avoid instantiating String objects; this is usually unnecessary since they are immutable and can be safely shared.

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.StringInstantiationRule

Example(s):

    private String bar = new String("bar"); // just do a String bar = "bar";

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/StringInstantiation" />

## StringToString

Since: PMD 1.0

Priority: Medium (3)

Avoid calling toString() on objects already known to be string instances; this is unnecessary.

This rule is defined by the following XPath expression:

    //MethodCall[pmd-java:matchesSig("java.lang.String#toString()")]

Example(s):

    private String baz() {
        String bar = "howdy";
        return bar.toString();
    }

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/StringToString" />

## TooFewBranchesForASwitchStatement

Deprecated

This rule has been renamed. Use instead: TooFewBranchesForSwitch

Deprecated

Since: PMD 4.2

Priority: Medium (3)

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.

Note: This rule was named TooFewBranchesForASwitchStatement before PMD 7.7.0.

This rule is defined by the following XPath expression:

    //(SwitchStatement | SwitchExpression)
      [ count(*) > 1 ] (: ignore empty switch blocks :)
      [ (count(*/SwitchLabel/*) + count(*/SwitchLabel[@Default = true()])) < $minimumNumberCaseForASwitch ]
      (: do not consider exhaustive switches unless there is a default case :)
      [@Exhaustive = false() or @DefaultCase = true()]

Example(s):

    // With a minimumNumberCaseForASwitch of 3
    public class Foo {
        public void bar(int condition) {
            switch (condition) {
                case 1:
                    instruction;
                    break;
                default:
                    break; // not enough for a 'switch' stmt, a simple 'if' stmt would have been more appropriate
            }
        }
    }

This rule has the following properties:

Name | Default Value | Description
--- | --- | ---
minimumNumberCaseForASwitch | 3 | Minimum number of branches for a switch

Use this rule with the default properties by just referencing it:

    <rule ref="category/java/performance.xml/TooFewBranchesForASwitchStatement" />

Use this rule and customize it:

    <rule ref="category/java/performance.xml/TooFewBranchesForASwitchStatement">
        <properties>
            <property name="minimumNumberCaseForASwitch" value="3" />
        </properties>
    </rule>

## TooFewBranchesForSwitch

Since: PMD 4.2

Priority: Medium (3)

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.

Note: This rule was named TooFewBranchesForASwitchStatement before PMD 7.7.0.

This rule is defined by the following XPath expression:

    //(SwitchStatement | SwitchExpression)
      [ count(*) > 1 ] (: ignore empty switch blocks :)
      [ (count(*/SwitchLabel/*) + count(*/SwitchLabel[@Default = true()])) < $minimumNumberCaseForASwitch ]
      (: do not consider exhaustive switches unless there is a default case :)
      [@Exhaustive = false() or @DefaultCase = true()]

Example(s):

    // With a minimumNumberCaseForASwitch of 3
    public class Foo {
        public void bar(int condition) {
            switch (condition) {
                case 1:
                    instruction;
                    break;
                default:
                    break; // not enough for a 'switch' stmt, a simple 'if' stmt would have been more appropriate
            }
        }
    }

This rule has the following properties:

Name | Default Value | Description
--- | --- | ---
minimumNumberCaseForASwitch | 3 | Minimum number of branches for a switch

Use this rule with the default properties by just referencing it:

    <rule ref="category/java/performance.xml/TooFewBranchesForSwitch" />

Use this rule and customize it:

    <rule ref="category/java/performance.xml/TooFewBranchesForSwitch">
        <properties>
            <property name="minimumNumberCaseForASwitch" value="3" />
        </properties>
    </rule>

## UseArrayListInsteadOfVector

Since: PMD 3.0

Priority: Medium (3)

ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required.

This rule is defined by the following XPath expression:

    //ConstructorCall/ClassType[pmd-java:typeIsExactly('java.util.Vector') or pmd-java:typeIsExactly('Vector')]

Example(s):

    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
        }
    }

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/UseArrayListInsteadOfVector" />

## UseArraysAsList

Since: PMD 3.5

Priority: Medium (3)

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).

This rule is defined by the following XPath expression:

    //ForStatement
      [ForInit
        [LocalVariableDeclaration
          [PrimitiveType[@Kind = 'int']]
          [VariableDeclarator[NumericLiteral[@IntLiteral][@Image = '0']]]
        ]
      ]
      [*[2]//FieldAccess[@Name = 'length']/VariableAccess[pmd-java:typeIs("java.lang.Object[]")]]
      [ForUpdate
        [StatementExpressionList
          [UnaryExpression[@Operator = '++']
           | AssignmentExpression[@Operator = '+='][NumericLiteral[@IntLiteral][@Image = '1']]]
        ]
      ]
      /*[last()][not(IfStatement)]/ExpressionStatement/
        MethodCall
          [pmd-java:matchesSig('java.util.List#add(_)')]
          [ArgumentList/ArrayAccess
            [VariableAccess[@Name = ancestor::ForStatement/ForInit/LocalVariableDeclaration/VariableDeclarator/VariableId/@Name]]
          ]
    |
    //ForeachStatement
      [VariableAccess[pmd-java:typeIs("java.lang.Object[]")]]
      /*[last()][not(IfStatement)]/ExpressionStatement/MethodCall
          [pmd-java:matchesSig('java.util.List#add(_)')]
          [ArgumentList
            [VariableAccess[@Name = ancestor::ForeachStatement/LocalVariableDeclaration/VariableDeclarator/VariableId/@Name]]
          ]

Example(s):

    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
            }
        }
    }

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/UseArraysAsList" />

## UseIndexOfChar

Since: PMD 3.5

Priority: Medium (3)

Use String.indexOf(char) when checking for the index of a single character; it executes faster.

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.UseIndexOfCharRule

Example(s):

    String s = "hello world";
    // avoid this
    if (s.indexOf("d") {}
    // instead do this
    if (s.indexOf('d') {}

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/UseIndexOfChar" />

## UseIOStreamsWithApacheCommonsFileItem

Since: PMD 6.25.0

Priority: Medium (3)

Problem: Use of FileItem.get() and FileItem.getString() could exhaust memory since they load the entire file into memory.

Solution: Use FileItem.getInputStream() and buffering.

This rule is defined by the following XPath expression:

    //MethodCall
        [@MethodName = 'get' or @MethodName = 'getString']
        [*[pmd-java:typeIs('org.apache.commons.fileupload.FileItem')]]

Example(s):

    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();
       }
    }

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/UseIOStreamsWithApacheCommonsFileItem" />

## UselessStringValueOf

Since: PMD 3.8

Priority: Medium (3)

No need to call String.valueOf to append to a string; just use the valueOf() argument directly.

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.UselessStringValueOfRule

Example(s):

    public String convert(int i) {
        String s;
        s = "a" + String.valueOf(i);    // not required
        s = "a" + i;                    // preferred approach
        return s;
    }

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/UselessStringValueOf" />

## UseStringBufferForStringAppends

Since: PMD 3.1

Priority: Medium (3)

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.

This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.UseStringBufferForStringAppendsRule

Example(s):

    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();
        }
    }

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/UseStringBufferForStringAppends" />

## UseStringBufferLength

Since: PMD 3.4

Priority: Medium (3)

Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toString().equals("") or StringBuffer.toString().length() == …

This rule is defined by the following XPath expression:

    //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='""']]
                                                /VariableId[pmd-java:modifiers() = 'final']/@Name]]
    |
    (: finds sb.toString().equals("") :)
    //MethodCall[pmd-java:matchesSig('_#equals(_)')
      and MethodCall[pmd-java:matchesSig('java.lang.AbstractStringBuilder#toString()')]
      and ArgumentList/StringLiteral[@Image='""']]

Example(s):

    StringBuffer sb = new StringBuffer();

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

    if (sb.length() == 0) {}                // preferred

Use this rule by referencing it:

    <rule ref="category/java/performance.xml/UseStringBufferLength" />