我试图打印出 a 的所有元素List
,但是它打印的是指针Object
而不是值。
这是我的打印代码...
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
谁能帮助我为什么它不打印元素的值。
以下内容很紧凑,避免了示例代码中的循环(并为您提供了漂亮的逗号):
System.out.println(Arrays.toString(list.toArray()));
但是,正如其他人指出的那样,如果您没有为列表中的对象实现明智的 toString() 方法,您将获得您正在观察的对象指针(实际上是哈希码)。无论它们是否在列表中,这都是正确的。
这是一些关于打印出列表组件的示例:
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;
}
}
从 Java 8 开始,List 继承了一个默认的“forEach”方法,您可以将它与方法引用“System.out::println”结合起来,如下所示:
list.forEach(System.out::println);
System.out.println(list);//toString() is easy and good enough for debugging.
toString()
ofAbstractCollection
将是干净和容易做到这一点。AbstractList
是 的子类AbstractCollection
,因此不需要 for 循环,也不需要 toArray()。
返回此集合的字符串表示形式。字符串表示由集合元素的列表组成,按其迭代器返回的顺序排列,用方括号 ("[]") 括起来。相邻元素由字符“、”(逗号和空格)分隔。通过 String.valueOf(Object) 将元素转换为字符串。
如果您在列表中使用任何自定义对象,例如 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]
使用String.join()
例如:
System.out.print(String.join("\n", list));
Java 8 Streams 方法...
list.stream().forEach(System.out::println);
列表中的对象必须已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 = Test$T1@19821f
t2 = 5
由于 T1 没有覆盖 toString 方法,它的实例 t1 打印出来的东西不是很有用。另一方面,T2 覆盖了 toString,所以我们控制它在 I/O 中使用时打印的内容,并且我们在屏幕上看到了一些更好的东西。
或者您可以简单地使用 Apache Commons 实用程序:
List<MyObject> myObjects = ...
System.out.println(ArrayUtils.toString(myObjects));
考虑List<String> stringList
可以使用Java 8结构以多种方式打印的 a:
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
一种方式(_
_ ConcurrentModificationException
_ _ 如文档中所述ArrayList
:
结构修改是添加或删除一个或多个元素或显式调整后备数组大小的任何操作;仅设置元素的值不是结构修改。
所以这意味着ArrayList.forEach
设置值是允许的,没有任何问题。并且在并发收集的情况下,例如ConcurrentLinkedQueue
迭代器将是弱一致的,这意味着forEach
允许传入的操作甚至进行结构更改而ConcurrentModificationException
不会引发异常。但是在这里,修改可能会或可能不会在该迭代中可见。
第二种方法 ( Stream.forEach
) -
顺序未定义。虽然它可能不会发生在顺序流中,但规范并不能保证它。还要求该动作本质上是不干扰的。如文档中所述:
此操作的行为是明确的非确定性的。对于并行流管道,此操作不能保证尊重流的遇到顺序,因为这样做会牺牲并行性的好处。
第三种方法 ( Stream.forEachOrdered
) -
该动作将按照流的遭遇顺序执行。因此,只要订单很重要,就可以毫不犹豫地使用forEachOrdered
。如文档中所述:
如果流具有定义的遇到顺序,则按照流的遇到顺序为此流的每个元素执行一个操作。
在迭代同步集合时,第一种方法将获取集合的锁一次,并将在所有调用操作方法中保持它,但在流的情况下,它们使用集合的拆分器,它不锁定并依赖于已经建立的非规则-干涉。如果在迭代期间修改了支持流的集合,ConcurrentModificationException
则会抛出异常或可能出现不一致的结果。
第四种方法(并行Stream.forEach
)-
如前所述,在并行流的情况下,不能保证遵守预期的相遇顺序。有可能在不同的线程中针对不同的元素执行操作,而forEachOrdered
.
第五种方法(并行Stream.forEachOrdered
)-将按源指定
的forEachOrdered
顺序处理元素,而不管流是顺序的还是并行的。所以将它与并行流一起使用是没有意义的。
我也遇到过类似的问题。我的代码:
List<Integer> leaveDatesList = new ArrayList<>();
.....inserted value in list.......
方式1:在for循环中打印列表
for(int i=0;i<leaveDatesList.size();i++){
System.out.println(leaveDatesList.get(i));
}
方式 2:在 forEach、for 循环中打印列表
for(Integer leave : leaveDatesList){
System.out.println(leave);
}
方式3:在java 8中打印列表
leaveDatesList.forEach(System.out::println);
但是,如果元素是对象,那么正如 Kshitij Mehta 所提到的,您需要在该对象中实现(覆盖)方法“toString”——如果它尚未实现——并让它从对象中返回一些有意义的东西,例如:
class Person {
private String firstName;
private String lastName;
@Override
public String toString() {
return this.firstName + " " + this.lastName;
}
}
对于 String 数组的列表
list.forEach(s -> System.out.println(Arrays.toString((String[]) s )));
For循环打印列表的内容:
List<String> myList = new ArrayList<String>();
myList.add("AA");
myList.add("BB");
for ( String elem : myList ) {
System.out.println("Element : "+elem);
}
结果 :
Element : AA
Element : BB
如果您想在一行中打印(仅供参考):
String strList = String.join(", ", myList);
System.out.println("Elements : "+strList);
结果 :
Elements : AA, BB
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]
.
这取决于存储在 中的对象类型List
,以及它是否具有toString()
方法的实现。System.out.println(list)
应该打印所有标准的 java 对象类型(String
,Long
等Integer
)。如果我们使用自定义对象类型,那么我们需要override
toString()
自定义对象的方法。
例子:
class Employee {
private String name;
private long id;
@Override
public String toString() {
return "name: " + this.name() +
", id: " + this.id();
}
}
测试:
class TestPrintList {
public static void main(String[] args) {
Employee employee1 =new Employee("test1", 123);
Employee employee2 =new Employee("test2", 453);
List<Employee> employees = new ArrayList(2);
employee.add(employee1);
employee.add(employee2);
System.out.println(employees);
}
}
list.stream().map(x -> x.getName()).forEach(System.out::println);
我写了一个转储函数,如果它没有覆盖 toString(),它基本上会打印出一个对象的公共成员。人们可以轻松地将其扩展为调用 getter。Java 文档:
使用以下规则将给定对象转储到 System.out:
- 如果 Object 是 Iterable,则转储其所有组件。
- 如果 Object 或其超类之一覆盖 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();
}
我现在正好在做这个...
List<Integer> a = Arrays.asList(1, 2, 3);
List<Integer> b = Arrays.asList(3, 4);
List<int[]> pairs = a.stream()
.flatMap(x -> b.stream().map(y -> new int[]{x, y}))
.collect(Collectors.toList());
Consumer<int[]> pretty = xs -> System.out.printf("\n(%d,%d)", xs[0], xs[1]);
pairs.forEach(pretty);
您对 java 11 的问题的解决方案是:
String separator = ", ";
String toPrint = list.stream().map(o -> String.valueOf(o)).collect(Collectors.joining(separator));
System.out.println(toPrint);
尝试根据需要覆盖 toString() 方法,该元素将被打印。所以打印的方法可以是这样的:
for(int i=0;i<list.size();i++){
System.out.println(list.get(i).toString());
}
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()));
}
你可以试试:
2D(或更多)
System.out.println(Arrays.deepToString(list.toArray()));
一维
System.out.println(Arrays.toString(list.toArray()))
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;
}
}