Java中与Python的format()函数相对应的方法是什么?

45

以下是两种字符串替换的方法:

name = "Tshepang"
"my name is {}".format(name)
"my name is " + name

我该如何使用Java实现类似于第一种方法的功能?

4个回答

49
name = "Paŭlo";
MessageFormat f = new MessageFormat("my name is {0}");
f.format(new Object[]{name});

或者更短:

MessageFormat.format("my name is {0}", name);

39
String s = String.format("something %s","name");

2
有没有办法避免指定类型(例如%s),就像Python的format()函数一样? - tshepang
@Tshepang,不幸的是,你不能像在Python中那样使用文字量来完成这个任务。所以你始终需要在String类上调用这个静态方法。 - Chris
@Chris:不确定你(或我)是否理解。我的意思是,我想要类似于String.format("我的名字是 {}", name)这样的东西。 - tshepang
@Tshepang 可以考虑查看 Java API 中 Formatter 类的文档,链接 - Anthony Grist
使用 {} 和 %s 有什么区别?是因为您不想指定传递的变量类型吗? - Chris
13
%s 占位符并不表示参数是一个字符串,而是要求将参数格式化为字符串。如果参数实现了 Formattable 接口,则调用其 formatTo 方法,否则调用其 toString 方法。因此,它可以用于任何对象,包括数字。 - Paŭlo Ebermann

3

Underscore-java有一个名为format()的静态方法。点击此处查看实例

import com.github.underscore.Underscore;

public class Main {
    public static void main(String[] args) {
        String name = "Tshepang";
        String formatted = Underscore.format("my name is {}", name);
        // my name is Tshepang
    }
}

0

你可以尝试this

package template.fstyle;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static java.util.Objects.nonNull;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;


@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class FStyleFinal {
    private static final String PLACEHOLDERS_KEY = "placeholders";
    private static final String VARIABLE_NAMES_KEY = "variableNames";
    private static final String PLACEHOLDER_PREFIX = "{{";
    private static final String PLACEHOLDER_SUFFIX = "}}";
    private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\{\\{\\s*([\\S]+)\\s*}}");

    private static Map<String, List<String>> toPlaceholdersAndVariableNames(String rawTemplate) {
        List<String> placeholders = newArrayList();
        List<String> variableNames = newArrayList();

        Matcher matcher = PLACEHOLDER_PATTERN.matcher(rawTemplate);
        while (matcher.find()) {
            for (int j = 0; j <= matcher.groupCount(); j++) {
                String s = matcher.group(j);
                if (StringUtils.startsWith(s, PLACEHOLDER_PREFIX) && StringUtils.endsWith(s, PLACEHOLDER_SUFFIX)) {
                    placeholders.add(s);
                } else if (!StringUtils.startsWith(s, PLACEHOLDER_PREFIX) && !StringUtils.endsWith(s, PLACEHOLDER_SUFFIX)) {
                    variableNames.add(s);
                }
            }
        }
        checkArgument(CollectionUtils.size(placeholders) == CollectionUtils.size(variableNames), "template engine error");

        Map<String, List<String>> map = newHashMap();
        map.put(PLACEHOLDERS_KEY, placeholders);
        map.put(VARIABLE_NAMES_KEY, variableNames);
        return map;
    }

    private static String toJavaTemplate(String rawTemplate, List<String> placeholders) {
        String javaTemplate = rawTemplate;
        for (String placeholder : placeholders) {
            javaTemplate = StringUtils.replaceOnce(javaTemplate, placeholder, "%s");
        }
        return javaTemplate;
    }

    private static Object[] toJavaTemplateRenderValues(Map<String, String> context, List<String> variableNames, boolean allowNull) {
        return variableNames.stream().map(name -> {
            String value = context.get(name);
            if (!allowNull) {
                checkArgument(nonNull(value), name + " should not be null");
            }
            return value;
        }).toArray();
    }

    private static Map<String, String> fromBeanToMap(Object bean, List<String> variableNames) {
        return variableNames.stream().distinct().map(name -> {
            String value = null;
            try {
                value = BeanUtils.getProperty(bean, name);
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                log.debug("fromBeanToMap error", e);
            }
            return Pair.of(name, value);
        }).filter(p -> nonNull(p.getRight())).collect(Collectors.toMap(Pair::getLeft, Pair::getRight));
    }

    public static String render(String rawTemplate, Map<String, String> context, boolean allowNull) {
        Map<String, List<String>> templateMeta = toPlaceholdersAndVariableNames(rawTemplate);
        List<String> placeholders = templateMeta.get(PLACEHOLDERS_KEY);
        List<String> variableNames = templateMeta.get(VARIABLE_NAMES_KEY);
        // transform template to java style template
        String javaTemplate = toJavaTemplate(rawTemplate, placeholders);
        Object[] renderValues = toJavaTemplateRenderValues(context, variableNames, allowNull);
        return String.format(javaTemplate, renderValues);
    }

    public static String render(String rawTemplate, Object bean, boolean allowNull) {
        Map<String, List<String>> templateMeta = toPlaceholdersAndVariableNames(rawTemplate);
        List<String> variableNames = templateMeta.get(VARIABLE_NAMES_KEY);
        Map<String, String> mapContext = fromBeanToMap(bean, variableNames);
        return render(rawTemplate, mapContext, allowNull);
    }

    public static void main(String[] args) {
        String template = "hello, my name is {{ name }}, and I am  {{age}} years old, a null value {{ not_exists }}";
        Map<String, String> context = newHashMap();
        context.put("name", "felix");
        context.put("age", "18");
        String s = render(template, context, true);
        log.info("{}", s);

        try {
            render(template, context, false);
        } catch (IllegalArgumentException e) {
            log.error("error", e);
        }
    }
}

示例输出:

[main] INFO template.fstyle.FStyleFinal - hello, my name is felix, and I am  18 years old, a null value null
[main] ERROR template.fstyle.FStyleFinal - error
java.lang.IllegalArgumentException: not_exists should not be null
    at com.google.common.base.Preconditions.checkArgument(Preconditions.java:142)
    at template.fstyle.FStyleFinal.lambda$toJavaTemplateRenderValues$0(FStyleFinal.java:69)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:545)
    at java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
    at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:438)
    at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:444)
    at template.fstyle.FStyleFinal.toJavaTemplateRenderValues(FStyleFinal.java:72)
    at template.fstyle.FStyleFinal.render(FStyleFinal.java:93)
    at template.fstyle.FStyleFinal.main(FStyleFinal.java:113)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接