Как распечатать все элементы списка в Java?
Я пытаюсь распечатать все элементы List
, однако он печатает указатель Object
, а не значение.
Это мой код печати...
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
Может ли кто-нибудь помочь мне, почему он не печатает значение элементов.
Ответы
Ответ 1
Вот пример получения распечатки компонента списка:
public class ListExample {
public static void main(String[] args) {
List<Model> models = new ArrayList<>();
// TODO: First create your model and add to models ArrayList, to prevent NullPointerException for trying this example
// Print the name from the list....
for(Model model : models) {
System.out.println(model.getName());
}
// Or like this...
for(int i = 0; i < models.size(); i++) {
System.out.println(models.get(i).getName());
}
}
}
class Model {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Ответ 2
Следующее является компактным и избегает цикла в вашем примере кода (и дает вам хорошие запятые):
System.out.println(Arrays.toString(list.toArray()));
Однако, как указывали другие, если у вас нет разумных методов toString(), реализованных для объектов внутри списка, вы получите указатели объектов (на самом деле, хэш-коды), которые вы наблюдаете. Это верно, находятся ли они в списке или нет.
Ответ 3
Так как Java 8, List наследует метод "forEach" по умолчанию, который вы можете комбинировать с ссылкой метода "System.out:: println" следующим образом:
list.forEach(System.out::println);
Ответ 4
System.out.println(list);//toString() is easy and good enough for debugging.
toString()
AbstractCollection
будет достаточно чистым и легким, чтобы сделать это. AbstractList
является подклассом AbstractCollection
, , поэтому нет необходимости в цикле и не требуется toArray().
Возвращает строковое представление этой коллекции. Строковое представление состоит из списка элементов коллекции в порядок, который они возвращают своим итератором, заключенные в квадратные скобки ( "[]" ). Смежные элементы разделяются символами "," (запятая и пространство). Элементы преобразуются в строки как String.valueOf(объект).
Если вы используете какой-либо пользовательский объект в своем списке, скажем, Student, вам нужно переопределить его метод toString()
(всегда полезно переопределить этот метод), чтобы иметь значимый результат
См. пример ниже:
public class TestPrintElements {
public static void main(String[] args) {
//Element is String, Integer,or other primitive type
List<String> sList = new ArrayList<String>();
sList.add("string1");
sList.add("string2");
System.out.println(sList);
//Element is custom type
Student st1=new Student(15,"Tom");
Student st2=new Student(16,"Kate");
List<Student> stList=new ArrayList<Student>();
stList.add(st1);
stList.add(st2);
System.out.println(stList);
}
}
public class Student{
private int age;
private String name;
public Student(int age, String name){
this.age=age;
this.name=name;
}
@Override
public String toString(){
return "student "+name+", age:" +age;
}
}
выход:
[string1, string2]
[student Tom age:15, student Kate age:16]
Ответ 5
Подход Java 8 Streams...
list.stream().forEach(System.out::println);
Ответ 6
Объекты в списке должны иметь toString
, чтобы они могли напечатать что-то значимое для экрана.
Вот быстрый тест, чтобы увидеть различия:
public class Test {
public class T1 {
public Integer x;
}
public class T2 {
public Integer x;
@Override
public String toString() {
return x.toString();
}
}
public void run() {
T1 t1 = new T1();
t1.x = 5;
System.out.println(t1);
T2 t2 = new T2();
t2.x = 5;
System.out.println(t2);
}
public static void main(String[] args) {
new Test().run();
}
}
И когда это выполняется, результаты, напечатанные на экране, следующие:
t1 = [email protected]
t2 = 5
Так как T1 не переопределяет метод toString, его экземпляр t1 выводится как нечто, что не очень полезно. С другой стороны, T2 переопределяет toString, поэтому мы контролируем, что он печатает, когда он используется в I/O, и мы видим что-то немного лучше на экране.
Ответ 7
Используя функции java 8.
import java.util.Arrays;
import java.util.List;
/**
* @author AJMAL SHA
*
*/
public class ForEach {
public static void main(String[] args) {
List<String> features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
(features).forEach(System.out::println);
}
}
Ответ 8
- Вы не указали, какие элементы содержатся в списке, если это примитивный тип данных, тогда вы можете распечатать элементы.
-
Но если элементы являются объектами, то, как сказал Кшити Мехта, вам нужно реализовать (переопределить) метод "toString" внутри этого объекта - если он еще не реализован - и позволить ему вернуть что-то, что означает полное изнутри объект, пример:
class Person {
private String firstName;
private String lastName;
@Override
public String toString() {
return this.firstName + " " + this.lastName;
}
}
Ответ 9
Я написал функцию дампа, которая в основном печатает публичные элементы объекта, если она не переопределила toString(). Его можно было легко расширить, чтобы вызвать геттеры.
Javadoc:
Сбрасывает заданный объект в System.out, используя следующие правила:
- Если объект Iterable, все его компоненты сбрасываются.
- Если объект или один из его суперклассов переопределяет toString(), "toString" сбрасывается
- Иначе метод вызывается рекурсивно для всех публичных членов Object
/**
* Dumps an given Object to System.out, using the following rules:<br>
* <ul>
* <li> If the Object is {@link Iterable}, all of its components are dumped.</li>
* <li> If the Object or one of its superclasses overrides {@link #toString()}, the "toString" is dumped</li>
* <li> Else the method is called recursively for all public members of the Object </li>
* </ul>
* @param input
* @throws Exception
*/
public static void dump(Object input) throws Exception{
dump(input, 0);
}
private static void dump(Object input, int depth) throws Exception{
if(input==null){
System.out.print("null\n"+indent(depth));
return;
}
Class<? extends Object> clazz = input.getClass();
System.out.print(clazz.getSimpleName()+" ");
if(input instanceof Iterable<?>){
for(Object o: ((Iterable<?>)input)){
System.out.print("\n"+indent(depth+1));
dump(o, depth+1);
}
}else if(clazz.getMethod("toString").getDeclaringClass().equals(Object.class)){
Field[] fields = clazz.getFields();
if(fields.length == 0){
System.out.print(input+"\n"+indent(depth));
}
System.out.print("\n"+indent(depth+1));
for(Field field: fields){
Object o = field.get(input);
String s = "|- "+field.getName()+": ";
System.out.print(s);
dump(o, depth+1);
}
}else{
System.out.print(input+"\n"+indent(depth));
}
}
private static String indent(int depth) {
StringBuilder sb = new StringBuilder();
for(int i=0; i<depth; i++)
sb.append(" ");
return sb.toString();
}
Ответ 10
System.out.println(list);
работает для меня.
Вот полный пример:
import java.util.List;
import java.util.ArrayList;
public class HelloWorld {
public static void main(String[] args) {
final List<String> list = new ArrayList<>();
list.add("Hello");
list.add("World");
System.out.println(list);
}
}
Откроется [Hello, World]
.
Ответ 11
list.stream().map(x -> x.getName()).forEach(System.out::println);
Ответ 12
Для списка массива String
list.forEach(s -> System.out.println(Arrays.toString((String[]) s )));
Ответ 13
Рассмотрим List<String> stringList
, который может быть напечатан многими способами с помощью конструкций Java 8:
stringList.forEach(System.out::println); // 1) Iterable.forEach
stringList.stream().forEach(System.out::println); // 2) Stream.forEach (order maintained generally but doc does not guarantee)
stringList.stream().forEachOrdered(System.out::println); // 3) Stream.forEachOrdered (order maintained always)
stringList.parallelStream().forEach(System.out::println); // 4) Parallel version of Stream.forEach (order not maintained)
stringList.parallelStream().forEachOrdered(System.out::println); // 5) Parallel version ofStream.forEachOrdered (order maintained always)
Как эти подходы отличаются друг от друга?
Первый подход (Iterable.forEach
) -
Итератор коллекции обычно используется и предназначен для fail-fast, что означает, что он бросит ConcurrentModificationException
, если базовая коллекция будет структурно модифицированный во время итерации. Как указано в doc для ArrayList
:
Структурная модификация - это любая операция, которая добавляет или удаляет одну или больше элементов или явно изменяет размер массива поддержки; просто установка значение элемента не является структурной модификацией.
Поэтому это означает, что для ArrayList.forEach
установка значения разрешается без каких-либо проблем. И в случае одновременного сбора, например. ConcurrentLinkedQueue
итератор будет слабо согласованный, что означает, что действия, переданные в forEach
, допускают даже структурные изменения без ConcurrentModificationException
исключение. Но здесь модификации могут быть или не быть видимыми в этой итерации.
Второй подход (Stream.forEach
) -
Заказ undefined. Хотя это может не произойти для последовательных потоков, но спецификация не гарантирует этого. Кроме того, действие должно быть неинтерферирующим в природе. Как упоминалось в doc:
Поведение этой операции явно недетерминировано. Для параллельные поточные трубопроводы, эта операция не гарантирует соблюдайте порядок столкновений потока, так как это принесет жертву преимущество parallelism.
Третий подход (Stream.forEachOrdered
) -
Действие будет выполняться в порядке вызова потока. Поэтому всякий раз, когда порядок имеет значение, используйте forEachOrdered
без второй мысли. Как упоминалось в doc:
Выполняет действие для каждого элемента этого потока, в встрече порядок потока, если поток имеет определенный порядок встреч.
Во время повторного использования синхронизированной коллекции первый подход будет принимать блокировку один раз и будет удерживать ее во всех методах вызовов к действию, но в случае потоков они используйте сборщик spliterator, который не блокирует и не использует уже установленные правила невмешательства. В случае, если сбор, поддерживающий поток, изменяется во время итерации a ConcurrentModificationException
, или может возникнуть непоследовательный результат.
Четвертый подход (Параллельный Stream.forEach
) -
Как уже упоминалось, нет гарантии уважать порядок встреч, как ожидалось, в случае параллельных потоков. Возможно, что действие выполняется в разных потоках для разных элементов, которые никогда не могут быть в случае с forEachOrdered
.
Пятый подход (Параллельный Stream.forEachOrdered
) -
forEachOrdered
будет обрабатывать элементы в порядке, указанном источником, независимо от того, является ли поток последовательным или параллельным. Поэтому нет смысла использовать это с параллельными потоками.
Ответ 14
List<String> textList= messageList.stream()
.map(Message::getText)
.collect(Collectors.toList());
textList.stream().forEach(System.out::println);
public class Message {
String name;
String text;
public Message(String name, String text) {
this.name = name;
this.text = text;
}
public String getName() {
return name;
}
public String getText() {
return text;
}
}
Ответ 15
public static void main(String[] args) {
answer(10,60);
}
public static void answer(int m,int k){
AtomicInteger n = new AtomicInteger(m);
Stream<Integer> stream = Stream.generate(() -> n.incrementAndGet()).limit(k);
System.out.println(Arrays.toString(stream.toArray()));
}
Ответ 16
попробуйте переопределить метод toString(), так как вы хотите, чтобы этот элемент был напечатан.
поэтому способ печати может быть следующим:
for(int i=0;i<list.size();i++){
System.out.println(list.get(i).toString());
}