Size: примеры (JAVA)
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)
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) Последовательный и параллельный подсчёт больших коллекций
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) Реализация собственной коллекции с ленивым подсчётом
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() в конкурентной очереди
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
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