Size: примеры (JAVA)

Примеры вызовов size и похожих способов
Раздел: Коллекции (Collection Framework) - List
size: int

Описание метода size()

В Java термин "size" чаще всего относится к методу size() в интерфейсе java.util.Collection и его реализациях (например, List, Set), а также к похожим свойствам и методам, возвращающим количество элементов или размер в разных типах данных. Метод Collection.size() не принимает аргументов и возвращает значение типа int - количество элементов в коллекции.

Ключевые варианты и соответствующие способы получения "размера":

  • Collection.size() - возвращает int; для большинства стандартных коллекций операция выполняется за O(1), так как размер хранится в поле.
  • Map.size() - возвращает число пар ключ-значение как int.
  • Массивы: свойство length (без скобок) возвращает int - длину массива.
  • Строки: String.length() возвращает int - число символов (UTF-16 code units).
  • Файлы: java.io.File.length() возвращает long - размер в байтах.
  • Потоки: Stream.count() возвращает long - число элементов в стриме (подсчет может быть затратным и выполнить терминальную операцию).

Возвращаемые значения и ограничения:

  • Коллекции возвращают неотрицательный int. Ноль означает пустую коллекцию.
  • Для очень больших коллекций возможен переполнение int, но стандартные коллекции используют int, поэтому при очень больших объёмах требуется альтернативный подход (например, подсчет в long через стримы или специализированные структуры).
  • В многопоточной среде значение size() может отражать состояние в момент вызова и измениться сразу после него. Для некоторых конкурентных коллекций подсчёт может быть дорогим или приблизительным.

Аргументы: отсутствуют. Метод вызывается без параметров.

Особенности реализации и производительность:

  • Большинство реализаций (ArrayList, HashSet, LinkedList) хранят поле size и возвращают его за O(1).
  • Некоторые конкурентные очереди (например, ConcurrentLinkedQueue) не поддерживают эффективный постоянный счётчик, поэтому size() может быть O(n) и дорогим.
  • Для параллельного подсчёта часто используется parallelStream().count() или специализированные методы в реализациях коллекций.

Краткое резюме: в Java для получения количества элементов используется несколько похожих API - главное различие между ними в типе возвращаемого значения и в производительности в многопоточных сценариях.

Короткие примеры использования

Каждый пример содержит исходный код и результат его выполнения.

import java.util.*;
public class Ex1 {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        list.add("a");
        list.add("b");
        System.out.println(list.size());
    }
}
2
import java.util.*;
public class Ex2 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4};
        System.out.println(arr.length);
    }
}
4
public class Ex3 {
    public static void main(String[] args) {
        String s = "Привет";
        System.out.println(s.length());
    }
}
6
import java.io.*;
public class Ex4 {
    public static void main(String[] args) throws Exception {
        File f = new File("build.gradle");
        System.out.println(f.exists() ? f.length() : -1);
    }
}
1234  // пример: размер файла в байтах или -1 если файл не найден
import java.util.concurrent.*;
public class Ex5 {
    public static void main(String[] args) {
        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue<>();
        for (int i = 0; i < 1000; i++) q.add(i);
        System.out.println(q.size());
    }
}
1000  // подсчёт может быть медленным для больших размеров

Похожие методы в Java и их особенности

  • isEmpty() - проверяет пустая ли коллекция; часто эффективнее, если требуется лишь булево значение (внутренне обычно делает size == 0).
  • String.length() - возвращает длину строки (не совпадает с числом логических символов при суррогатных парах).
  • Stream.count() - возвращает long и выполняет терминальную операцию; полезно для подсчёта после фильтрации или трансформации.
  • Array.length - свойство для массивов (без вызова метода).
  • Map.size() - для отображений; при необходимости работать с ключами или значениями предпочтительно использовать map.keySet().size() или map.entrySet().size(), но они эквивалентны.

Когда что предпочтительнее:

  • Если требуется только узнать пустая ли коллекция - использовать isEmpty().
  • Если нужна длина строки - String.length(), а не size() (его нет у String).
  • При необходимости подсчитать элементы после фильтрации - использовать поток stream().filter(...).count().

Аналоги в других языках и отличия

Ниже приведены короткие примеры аналогичных способов получения размера в разных языках и краткие отличия.

PHP

$a = [1,2,3];
echo count($a);
3

count возвращает количество элементов; аналогично sizeof.

JavaScript

const arr = [1,2,3];
console.log(arr.length);
const map = new Map([[1, 'a'], [2, 'b']]);
console.log(map.size);
3
2

Для массивов и строк используется .length, для Map и Set - .size; тип возвращаемого значения Number.

Python

a = [1,2,3]
print(len(a))
3

len() универсален для контейнеров; возвращает int (вплоть до больших чисел).

SQL

SELECT COUNT(*) FROM users;
-- возвращает число строк в таблице

C#

var list = new List{1,2,3};
Console.WriteLine(list.Count);
3

Коллекции .Count или массивы .Length; Count - свойство, не метод.

Lua

local t = {1,2,3}
print(#t)
3

# возвращает длину последовательностей, в таблицах с разрывами поведение может отличаться.

Go

arr := []int{1,2,3}
fmt.Println(len(arr))
3

len возвращает длину для срезов, массивов, карт и строк (для строк - байты).

Kotlin

val list = listOf(1,2,3)
println(list.size)
val arr = arrayOf(1,2,3)
println(arr.size)
3
3

Kotlin использует свойство size для коллекций и массивов и возвращает Int.

Отличия от Java: в Java часто используется метод size() у Collection и свойство length у массивов; в других языках единый подход (len, length, size) более распространён.

Типичные ошибки при использовании size()

  • NullPointerException: вызов size() на ссылке null. Пример:
import java.util.List;
public class Err1 {
    public static void main(String[] args) {
        List l = null;
        System.out.println(l.size());
    }
}
Exception in thread "main" java.lang.NullPointerException
    at Err1.main(Err1.java:5)
  • Путаница между массивом и коллекцией: использование size() для массива приведёт к ошибке компиляции. Пример:
public class Err2 {
    public static void main(String[] args) {
        int[] a = {1,2,3};
        System.out.println(a.size());
    }
}
Err2.java:4: error: cannot find symbol
        System.out.println(a.size());
                           ^
  symbol:   method size()
  location: variable a of type int[]
  • Производительность и блокировки: вызов size() на некоторых конкурентных структурах может быть дорогим или неточным при одновременных модификациях. Использование внутри цикла, который модифицирует коллекцию, может привести к неожиданным результатам или исключению ConcurrentModificationException при итерации стандартных коллекций.
import java.util.*;
public class Err3 {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        list.add(1);
        for (Integer i : list) {
            list.add(2); // модификация во время итерации
        }
    }
}
Exception in thread "main" java.util.ConcurrentModificationException
    at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:xxx)
    ...

Рекомендация: проверять на null до вызова, использовать isEmpty() если требуется только булево значение и быть внимательным к многопоточному доступу и возможным затратам при подсчёте.

Изменения и актуальные особенности

Интерфейс Collection.size() и поведение большинства стандартных реализаций не претерпели значительных изменений в последних версиях Java. Тем не менее появились дополнения, влияющие на подсчёт в многопоточных контекстах и альтернативные методы:

  • В Java 8 и позднее расширены возможности потоков: Stream.count() используется для подсчёта элементов после операций фильтрации и трансформации.
  • ConcurrentHashMap содержит методы для получения более точной или масштабируемой оценки числа элементов (например, mappingCount() возвращает long для больших объёмов).
  • Работа с большими коллекциями всё чаще требует применения типов с возвратом long для избежания переполнения int, поэтому в специфичных случаях применяется подсчёт через стримы или кастомную логику.

Расширенные и редко встречающиеся примеры

Подробные сценарии с пояснениями и реальными выводами.

1) Подсчёт после фильтрации через стрим (возвращается long)

Пример java
import java.util.*;
public class Adv1 {
    public static void main(String[] args) {
        List list = Arrays.asList("one", "two", "three", "four");
        long c = list.stream().filter(s -> s.length() == 3).count();
        System.out.println(c);
    }
}
2

Пояснение: stream().count() возвращает long, полезно при больших данных.

2) Последовательный и параллельный подсчёт больших коллекций

Пример java
import java.util.*;
public class Adv2 {
    public static void main(String[] args) {
        List big = new ArrayList<>();
        for (int i = 0; i < 1_000_000; i++) big.add(i);
        long t0 = System.currentTimeMillis();
        long c1 = big.stream().filter(i -> i % 2 == 0).count();
        long t1 = System.currentTimeMillis();
        long c2 = big.parallelStream().filter(i -> i % 2 == 0).count();
        long t2 = System.currentTimeMillis();
        System.out.println(c1 + " seq ms=" + (t1-t0));
        System.out.println(c2 + " par ms=" + (t2-t1));
    }
}
500000 seq ms=XX
500000 par ms=YY

Пояснение: параллельный подсчёт может быть быстрее при тяжёлой фильтрации и достаточном количестве ядер, но накладные расходы могут сделать его медленнее для лёгких операций.

3) Реализация собственной коллекции с ленивым подсчётом

Пример java
import java.util.*;

class LazyCollection extends AbstractCollection {
    private final Supplier> supplier;
    private Collection impl;
    public LazyCollection(Supplier> supplier) {
        this.supplier = supplier;
    }
    private Collection ensure() {
        if (impl == null) impl = supplier.get();
        return impl;
    }
    @Override
    public Iterator iterator() { return ensure().iterator(); }
    @Override
    public int size() { return ensure().size(); }
}

public class Adv3 {
    public static void main(String[] args) {
        LazyCollection c = new LazyCollection<>(() -> { 
            List l = new ArrayList<>();
            for (int i=0;i<100;i++) l.add(i);
            return l;
        });
        System.out.println(c.size());
    }
}
100

Пояснение: размер вычисляется только при первом обращении благодаря ленивой инициализации.

4) Непредсказуемость size() в конкурентной очереди

Пример java
import java.util.concurrent.*;
public class Adv4 {
    public static void main(String[] args) throws InterruptedException {
        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue<>();
        for (int i=0;i<1000;i++) q.add(i);
        Thread t = new Thread(() -> {
            for (int i=0;i<500;i++) q.poll();
        });
        t.start();
        System.out.println(q.size());
        t.join();
        System.out.println(q.size());
    }
}
1000
500

Пояснение: первый вызов size() может вернуть 1000 до удаления в другом потоке; в многопоточном окружении значение является снимком на момент вызова и может быстро измениться.

5) Подсчёт файлов в каталоге через NIO

Пример java
import java.nio.file.*;
public class Adv5 {
    public static void main(String[] args) throws Exception {
        long count = Files.list(Paths.get(".")).count();
        System.out.println(count);
    }
}
42  // число элементов в текущей директории

Пояснение: Files.list возвращает Stream, count() выполняет терминальную операцию и закрывает поток.

джава size function comments

En
Size Returns the number of elements in this list