Как оптимизировать этот метод для разбиения строки на куски? - PullRequest
2 голосов
/ 21 мая 2009

Вот метод. Я хочу знать, нарушаю ли я какие-либо передовые методы здесь, или я делаю что-то не так в том, что касается языка.

private List<String> breakStringInChunks(String text, int chunkSize) {
        List<String> chunks = new ArrayList<String>();
        String temporary = "";
        int numberOfChunks = text.length() / chunkSize;
        int beginIndex = 0;
        int endIndex = 0;

        // Add one iteration if numberOfChunks*chunkSize is less than the length of text.
        if ((numberOfChunks * chunkSize) < text.length()) {
            numberOfChunks++;
        }

        // Cut strings and add in the list.
        for (int i = 0; i < numberOfChunks; i++) {
            endIndex+=chunkSize;
            if ((i + 1) == numberOfChunks) {
                temporary = text.substring(beginIndex);
            }
            else {
                temporary = text.substring(beginIndex, endIndex);
            }
            beginIndex=endIndex;
            chunks.add(temporary);
        }

        return chunks;
    }

Ответы [ 7 ]

4 голосов
/ 21 мая 2009

Сжатие еще меньше и позволяет избежать возможного изменения размера результирующего списка.

private static List<String> breakStringInChunks(final String text, final int chunkSize) {
    final int numChunks = 0 == (text.length() % chunkSize) ? text.length() / chunkSize : 1 + (text.length() / chunkSize);
    final List<String> chunks = new ArrayList<String>(numChunks);
    for (int startIndex = 0; startIndex < text.length(); startIndex += chunkSize) {
        final int endIndex = Math.min(text.length(), startIndex + chunkSize);
        chunks.add(text.substring(startIndex, endIndex));
    }
    return chunks;
}
1 голос
/ 21 мая 2009

Если я не пойму ваше намерение, это выглядит как огромное излишество и довольно часто использует создание строк, что делает алгоритм совершенно неэффективным в Java, поскольку строки неизменяемы.

Попробуйте это:

public List<String> breakStringsInChunks(String text,int chunkSize) {
    if (chunkSize<=1) {
        throw new IllegalArgumentException("Chunk size must be positive");
    }
    if (text==null || text.isEmpty()) {
        return Collections.emptyList();
    }

    List<String> chunks= new LinkedList<String>();

    int index=0;
    int len = text.length();

    //guaranteed to succeed at least once since 0 length strings we're taken care of
    do {
        chunks.add(text.substring(index, Math.min(index + chunkSize, len)));
        index+=chunkSize;
    } while (index<len);

    return chunks;
}
1 голос
/ 21 мая 2009

Это немного многословно, и нет необходимости объявлять строку temporary в начале вашего метода, что может сделать сборку мусора немного медленнее. Следующее было бы более коротким:

private List<String> breakStringInChunks(String text, int chunkSize) {
    int nChunks = (int)Math.ceil(((double)text.length())/chunkSize));
    List<String> chunks = new ArrayList<String>(nChunks);
    // Cut strings and add in the list.
    for (int i = 0; i < text.length(); i+=chunkSize) {
        int endIndex=i+chunksize;
        if (endIndex >= text.length()) {
            chunks.add(text.substring(i));
        } else {
            chunks.add(text.substring(i, endIndex));
        }
    }
    return chunks;
}

Одна хорошая вещь в вашем методе и приведенном выше тексте состоит в том, что, поскольку вы всегда вызываете substring () для исходной строки, Java будет ссылаться только на исходный массив символов, поэтому это сэкономит вам некоторые ресурсы памяти.

Я думаю, } else { - более распространенный стандарт кодирования для Java.

0 голосов
/ 21 мая 2009

Вот мой. Не сильно отличается от некоторых других ответов, но зависит от теста, fwiw.

public class ChunkTest extends TestCase {
    public void testEmpty() throws Exception {
        assertEquals(0, breakStringInChunks("", 1).size());
    }

    public void testOneChunk() throws Exception {
        String s = "abc";
        List<String> chunks = breakStringInChunks(s, s.length());
        assertEquals(s, chunks.get(0));
        assertEquals(1, chunks.size());
    }

    public void testPartialChunk() throws Exception {
        String s = "abc";
        List<String> chunks = breakStringInChunks(s, s.length() + 1);
        assertEquals(s, chunks.get(0));
        assertEquals(1, chunks.size());
    }

    public void testTwoChunks() throws Exception {
        String s = "abc";
        List<String> chunks = breakStringInChunks(s, 2);
        assertEquals("ab", chunks.get(0));
        assertEquals("c", chunks.get(1));
        assertEquals(2, chunks.size());
    }

    public void testTwoEvenChunks() throws Exception {
        String s = "abcd";
        List<String> chunks = breakStringInChunks(s, 2);
        assertEquals("ab", chunks.get(0));
        assertEquals("cd", chunks.get(1));
    }

    private List<String> breakStringInChunks(String text, int chunkSize) {
        if (text.isEmpty())
            return Collections.emptyList();
        int n = (text.length() + chunkSize - 1) / chunkSize;
        List<String> chunks = new ArrayList<String>(n);
        for (int i = 0; i < n; ++i)
            chunks.add(text.substring(i * chunkSize, Math.min((i + 1) * chunkSize, text.length())));
        return chunks;
    }
}
0 голосов
/ 21 мая 2009

Как насчет этого?

private List<String> breakStringInChunks(String text, int chunkSize)
{
    List<String> chunks = new ArrayList<String>();
    while (text.length() > 0)
    {
        if (chunkSize > text.length())
        {
            chunkSize = text.length();
        }
        chunks.add(text.substring(0, chunkSize));
        text = text.substring(chunkSize);
    }
    return chunks;
}
0 голосов
/ 21 мая 2009

Вот мое решение. Я попытался реализовать это, чтобы быть очень эффективным:

public static List<String> breakStringInChunks(String text, int chunkSize) {
    if (chunkSize < 2) {
        throw new IllegalArgumentException("Chunk size must be > 1");
    }
    if (null == text || text.isEmpty()) {
        return Collections.emptyList();
    }

    List<String> chunks = new ArrayList<String>(1 + (text.length() / chunkSize));

    int length = text.length() - (text.length() % chunkSize);

    for (int i = 0; i < length;) {
        chunks.add(text.substring(i, i += chunkSize));
    }
    if (length < text.length())
        chunks.add(text.substring(length));

    return chunks;
}
0 голосов
/ 21 мая 2009
public static final List<String> chunk(final String text, final int chunkSize) {
    // Figure out how many chunks we are going to make.
    final int textLength = text.length();
    final int numberOfChunks =
        textLength % chunkSize == 0
        ? textLength / chunkSize
        : textLength / chunkSize + 1;

    // Create an array list of just the right size.
    final ArrayList<String> chunks = new ArrayList<String>(numberOfChunks);

    // Do all the chunking but the last one - here we know that all chunks
    // are exactly chunkSize long.
    for (int i = 0; i < numberOfChunks - 1; i++) {
        chunks.add(text.substring(i * chunkSize, (i + 1) * chunkSize));
    }

    // Add final chunk, which may be shorter than chunkSize, so we use textLength
    // as the end index.
    chunks.add(text.substring((numberOfChunks - 1) * chunkSize, textLength));

    return chunks;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...