实现CharSequence以使用String.join?

时间:2016-05-15 15:09:30

标签: java string collections tostring charsequence

我有一组全部覆盖toString()的对象。 我想将它们写入控制台或连接到字符串,基本上为集合创建toString()

我可以使用for循环来实现这一目标。 String.join()似乎是一种更好的方式,因为它消除了显式循环:

import java.util.ArrayList;

public class Foo
{
    private double member;

    public Foo()
    {
        member = Math.random();
    }

    @Override
    public String toString()
    {
        return "I'm foo " + member;
    }

    public static void main(String[] args)
    {
        ArrayList<Foo> foos = new ArrayList<>();
        foos.add(new Foo());
        foos.add(new Foo());
        foos.add(new Foo());
        foos.add(new Foo());
        foos.add(new Foo());
        foos.add(new Foo());

        // print collection with loop
        for (Foo foo : foos)
        {
            System.out.println(foo);
        }

        // print collection with String.join
        System.out.println(String.join(System.lineSeparator(), foos));  // fails
    }
}

要使System.out.println()生效,请调用toString()方法。不必明确实现任何接口。这似乎很容易,也是一种常见的做法。

但是,要让String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)工作,仅使用toString()方法是不够的。我需要一个Iterable<? extends CharSequence>,这意味着Foo应该实现CharSequence

现在我通过委托toString()快速实现了该界面:

import java.util.ArrayList;
import java.util.stream.IntStream;

import java.lang.CharSequence;

public class Foo implements CharSequence
{
    private double member;

    public Foo()
    {
        member = Math.random();
    }

    @Override
    public char charAt(int index)
    {
        return toString().charAt(index);
    }

    @Override
    public IntStream chars()
    {
        return toString().chars();
    }

    @Override
    public IntStream codePoints()
    {
        return toString().codePoints();
    }

    @Override
    public int length()
    {
        return toString().length();
    }

    @Override
    public CharSequence subSequence(int start, int end)
    {
        return toString().subSequence(start, end);
    }

    @Override
    public String toString()
    {
        return "I'm foo " + member;
    }

    public static void main(String[] args)
    {
        ArrayList<Foo> foos = new ArrayList<>();
        foos.add(new Foo());
        foos.add(new Foo());
        foos.add(new Foo());
        foos.add(new Foo());
        foos.add(new Foo());
        foos.add(new Foo());

        System.out.println(String.join(System.lineSeparator(), foos));  
    }
}

但这似乎是相当多的代码,在这种情况下没有做太多的事情,除了保证将对象转换为String的可能性,Object每个toString()无论如何都以String.join()

解决方案中引入的样板代码大于它删除的样板代码。

如何使用side_effect使课程更好?

我应该走那条路并实现界面还是应该动态运行一些转换?

1 个答案:

答案 0 :(得分:3)

根据用途,该路由可能效率低下,因为每次调用CharSequence方法都会重新调用toString。例如,如果某个方法试图迭代每个字符,那么您就会看到糟糕的表现。由于您使用的是Java 8,为什么不使用Streams API?

System.out.println(foos.stream()
        .map(Object::toString)
        .collect(Collectors.joining(System.lineSeparator())));