[Изящно не обрабатывать конечные и ведущие нули / пустые тары. Теперь работает лучше.]
Я использую Google Guava (не официальную Java, но чертовски хороший набор пакетов). Я предлагаю это, так как кажется, что вы смотрели на Joiner, но затем отвергли это. Итак, поскольку вы были открыты для использования Joiner в какой-то момент, может быть, вы хотите посмотреть на это снова:
package testCode;
import java.util.List;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
public class TestClass {
Joiner joinComma = Joiner.on(", ");
Joiner joinAndForTwo = Joiner.on(" and ");
Joiner joinAndForMoreThanTwo = Joiner.on(", and ");
public String joinWithAnd(List<String> elements) {
ImmutableList<String> elementsNoNullsOrEmpties = new ImmutableList.Builder<String>()
.addAll(Iterables.filter(elements, new Predicate<String>() {
@Override
public boolean apply(String arg0) {
return !Strings.isNullOrEmpty(arg0);
}
})).build();
if (elementsNoNullsOrEmpties.size() == 0) {
return null;
} else if (elementsNoNullsOrEmpties.size() == 1) {
return Iterables.getOnlyElement(elementsNoNullsOrEmpties);
} else if (elementsNoNullsOrEmpties.size() == 2) {
return joinAndForTwo.join(elementsNoNullsOrEmpties);
} else {
final List<String> leadingElements = elementsNoNullsOrEmpties
.subList(0, elementsNoNullsOrEmpties.size() - 1);
final String trailingElement = elementsNoNullsOrEmpties
.get(elementsNoNullsOrEmpties.size() - 1);
return joinAndForMoreThanTwo.join(joinComma.join(leadingElements),
trailingElement);
}
}
}
И тестовый драйвер:
package testCode;
import java.util.List;
import com.google.common.collect.Lists;
public class TestMain {
static List<String> test1 = Lists.newArrayList();
static List<String> test2 = Lists.newArrayList("");
static List<String> test3 = Lists.newArrayList("a");
static List<String> test4 = Lists.newArrayList("a", "b");
static List<String> test5 = Lists.newArrayList("a", "b", "c", "d");
static List<String> test6 = Lists.newArrayList("a", "b", "c", null, "d");
static List<String> test7 = Lists.newArrayList("a", "b", "c", null);
static List<String> test8 = Lists.newArrayList("a", "b", "", "", null, "c",
null);
static List<String> test9 = Lists.newArrayList("", "a", "b", "c", null);
static List<String> test10 = Lists.newArrayList(null, "a", "b", "c", null);
public static void main(String[] args) {
TestClass testClass = new TestClass();
System.out.println(testClass.joinWithAnd(test1));
System.out.println(testClass.joinWithAnd(test2));
System.out.println(testClass.joinWithAnd(test3));
System.out.println(testClass.joinWithAnd(test4));
System.out.println(testClass.joinWithAnd(test5));
System.out.println(testClass.joinWithAnd(test6));
System.out.println(testClass.joinWithAnd(test7));
System.out.println(testClass.joinWithAnd(test8));
System.out.println(testClass.joinWithAnd(test9));
System.out.println(testClass.joinWithAnd(test10));
}
}
И вывод:
нуль
нуль
а и б
a, b, c и d
a, b, c и d
а, б и в
а, б и в
а, б и в
а, б и в
Мне это нравится, потому что он не выполняет сращивание строк. Он разбивает предоставленный список строк, а затем корректно склеивает их вместе, используя правила, основанные на количестве строковых элементов, не возвращаясь и не вставляя после себя «и» после факта. Я также обрабатываю все виды крайних случаев для нулей / пустых мест, появляющихся в начале, конце или середине списка строк. Возможно, вам гарантировано, что этого не произойдет, поэтому вы можете упростить это решение.
[Мой метод немного отличается от вашего тем, что, когда у меня ровно два элемента, я не ставлю запятую после первого элемента и перед «и», в то время как для трех или более существует запятая перед "и". Это вещь стиля. Легко настроить в зависимости от того, как запятые должны работать.]