Como retornar vários objetos de um método Java?


172

Eu quero retornar dois objetos de um método Java e fiquei pensando o que poderia ser uma boa maneira de fazer isso?

As possíveis maneiras em que posso pensar são: retornar a HashMap( uma vez que os dois objetos estão relacionados) ou retornar um ArrayListdos Objectobjetos.

Para ser mais preciso, os dois objetos que quero retornar são (a) Listde objetos e (b) nomes separados por vírgula.

Eu quero retornar esses dois objetos de um método porque não quero percorrer a lista de objetos para obter os nomes separados por vírgula (o que posso fazer no mesmo loop neste método).

De alguma forma, retornar a HashMapnão parece uma maneira muito elegante de fazê-lo.


1
A lista e os CSVs são basicamente visualizações diferentes dos mesmos dados? Parece que o que você precisa é de um Objeto em que você tenha uma única Listreferência e uma espécie de tabela de pesquisa.
James P.

Respostas:


128

Se você deseja retornar dois objetos, geralmente deseja retornar um único objeto que encapsule os dois objetos.

Você pode retornar uma lista de NamedObject objetos como este:

public class NamedObject<T> {
  public final String name;
  public final T object;

  public NamedObject(String name, T object) {
    this.name = name;
    this.object = object;
  }
}

Então você pode facilmente retornar um List<NamedObject<WhateverTypeYouWant>> .

Além disso: Por que você deseja retornar uma lista de nomes separados por vírgula em vez de a List<String>? Ou melhor ainda, retorne a Map<String,TheObjectType>com as chaves sendo os nomes e os valores dos objetos (a menos que seus objetos tenham especificado a ordem, nesse caso, a NavigableMappode ser o que você deseja.


O motivo para retornar a lista separada por vírgula é: Se eu não criar a lista aqui, precisaria fazer isso no chamador percorrendo os objetos (o valor CS é necessário). Talvez eu esteja pré-otimizando desnecessariamente.
Jagmal

2
Eu sempre me perguntei por que o Java não tem uma classe Pair <T, U> por esse motivo.
David Koelle

Jagmal: sim, se o único motivo para retornar a lista separada por vírgula é essa otimização, esqueça-a.
Joachim Sauer

Isso só funciona bem se os itens que você deseja devolver forem da mesma classe ou, pelo menos, tiverem um ancestral em comum. Quero dizer, usar Object no lugar de WhateverTypeYouWant não é muito legal.
David Hanak

@ David: Eu concordo que o uso de objetos aqui não é muito elegante, mas, em seguida, retorne objetos sem nenhum ancestral comum (exceto Objeto, é claro) não é muito legal também. Eu diria até que é um cheiro de código, se você precisar.
Joachim Sauer

69

Se você sabe que retornará dois objetos, também poderá usar um par genérico:

public class Pair<A,B> {
    public final A a;
    public final B b;

    public Pair(A a, B b) {
        this.a = a;
        this.b = b;
    }
};

Editar Uma implementação mais completa do acima:

package util;

public class Pair<A,B> {

    public static <P, Q> Pair<P, Q> makePair(P p, Q q) {
        return new Pair<P, Q>(p, q);
    }

    public final A a;
    public final B b;

    public Pair(A a, B b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((a == null) ? 0 : a.hashCode());
        result = prime * result + ((b == null) ? 0 : b.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        @SuppressWarnings("rawtypes")
        Pair other = (Pair) obj;
        if (a == null) {
            if (other.a != null) {
                return false;
            }
        } else if (!a.equals(other.a)) {
            return false;
        }
        if (b == null) {
            if (other.b != null) {
                return false;
            }
        } else if (!b.equals(other.b)) {
            return false;
        }
        return true;
    }

    public boolean isInstance(Class<?> classA, Class<?> classB) {
        return classA.isInstance(a) && classB.isInstance(b);
    }

    @SuppressWarnings("unchecked")
    public static <P, Q> Pair<P, Q> cast(Pair<?, ?> pair, Class<P> pClass, Class<Q> qClass) {

        if (pair.isInstance(pClass, qClass)) {
            return (Pair<P, Q>) pair;
        }

        throw new ClassCastException();

    }

}

Observações, principalmente sobre a oxidação com Java e genéricos:

  • ambos ae bsão imutáveis.
  • makePairO método estático ajuda na digitação da placa da caldeira, que o operador de diamante no Java 7 tornará menos irritante. Há algum trabalho para tornar esta re: genéricos realmente agradável, mas deve estar ok agora. (cf. PECS)
  • hashcodee equalssão gerados pelo eclipse.
  • a conversão do tempo de compilação no castmétodo está correta, mas não parece correta.
  • Não tenho certeza se os curingas isInstancesão necessários.
  • Acabei de escrever isso em resposta a comentários, apenas para fins ilustrativos.

Normalmente, tenho essa aula em cada código base em que trabalho. Eu também acrescentaria: uma implementação hashCode / igual a, e possivelmente um método isInstance () e cast () estático.
jamesh

Claro, existem muitas maneiras de tornar essa classe mais inteligente e mais conveniente de usar. A versão acima inclui o que é suficiente em uma declaração única.
David Hanak 21/01/2009

@jamesh: você se importa de escrever seu par aqui em detalhes? Eu gostaria de saber como fica depois de fornecer "uma implementação hashCode / igual a, e possivelmente um método estático isInstance () e cast ()". Obrigado.
Qiang Li

@ QiangLi - eu normalmente gere os métodos hashcode e iguais. O método da instância isInstance pega duas classes e garante que os a & b da instância sejam instâncias dessas classes. O elenco pega um par <?,?> E o lança com cuidado para um par <A, B>. As implementações deve ser bastante fácil (dica: Class.cast (), Class.isInstance ())
jamesh

2
Essa é uma Pairimplementação muito boa . Uma pequena alteração que eu faria: adicione uma mensagem ao ClassCastException. Caso contrário, a depuração se tornará um pesadelo se isso falhar por algum motivo. (e os rawtypes suprimir-avisos seria desnecessário se você tivesse convertido para Pair<?,?>(que funciona, porque você só precisa de Objectmétodos de ae b) Você se importa se eu ajustar o código.?
Joachim Sauer

25

Caso o método que você está chamando seja privado ou chamado de um local, tente

return new Object[]{value1, value2};

O chamador se parece com:

Object[] temp=myMethod(parameters);
Type1 value1=(Type1)temp[0];  //For code clarity: temp[0] is not descriptive
Type2 value2=(Type2)temp[1];

O exemplo do par de David Hanak não tem benefício sintático e é limitado a dois valores.

return new Pair<Type1,Type2>(value1, value2);

E o chamador se parece com:

Pair<Type1, Type2> temp=myMethod(parameters);
Type1 value1=temp.a;  //For code clarity: temp.a is not descriptive
Type2 value2=temp.b;

7
Par tem o benefício de controle tipo de classe
Hlex

5
IMHO, não siga este caminho - a declaração diz muito pouco sobre os valores de retorno esperados. AFAIK, é mais amplamente preferido criar classes genéricas que especificam quantos parâmetros estão sendo retornados e o tipo desses parâmetros. Pair<T1, T2>, Tuple<T1, T2, T3>, Tuple<T1, T2, T3, T4>, Etc. Em seguida, uma específicas de uso mostra o número e tipos de parâmetros Pair<int, String> temp = ...ou o que quer.
Home

22

Você pode usar qualquer uma das seguintes maneiras:

private static final int RETURN_COUNT = 2;
private static final int VALUE_A = 0;
private static final int VALUE_B = 1;
private static final String A = "a";
private static final String B = "b";

1) Usando matriz

private static String[] methodWithArrayResult() {
    //...
    return new String[]{"valueA", "valueB"};
}

private static void usingArrayResultTest() {
    String[] result = methodWithArrayResult();
    System.out.println();
    System.out.println("A = " + result[VALUE_A]);
    System.out.println("B = " + result[VALUE_B]);
}

2) Usando ArrayList

private static List<String> methodWithListResult() {
    //...
    return Arrays.asList("valueA", "valueB");
}

private static void usingListResultTest() {
    List<String> result = methodWithListResult();
    System.out.println();
    System.out.println("A = " + result.get(VALUE_A));
    System.out.println("B = " + result.get(VALUE_B));
}

3) Usando o HashMap

private static Map<String, String> methodWithMapResult() {
    Map<String, String> result = new HashMap<>(RETURN_COUNT);
    result.put(A, "valueA");
    result.put(B, "valueB");
    //...
    return result;
}

private static void usingMapResultTest() {
    Map<String, String> result = methodWithMapResult();
    System.out.println();
    System.out.println("A = " + result.get(A));
    System.out.println("B = " + result.get(B));
}

4) Usando sua classe de contêiner personalizado

private static class MyContainer<M,N> {
    private final M first;
    private final N second;

    public MyContainer(M first, N second) {
        this.first = first;
        this.second = second;
    }

    public M getFirst() {
        return first;
    }

    public N getSecond() {
        return second;
    }

    // + hashcode, equals, toString if need
}

private static MyContainer<String, String> methodWithContainerResult() {
    //...
    return new MyContainer("valueA", "valueB");
}

private static void usingContainerResultTest() {
    MyContainer<String, String> result = methodWithContainerResult();
    System.out.println();
    System.out.println("A = " + result.getFirst());
    System.out.println("B = " + result.getSecond());
}

5) Usando AbstractMap.simpleEntry

private static AbstractMap.SimpleEntry<String, String> methodWithAbstractMapSimpleEntryResult() {
    //...
    return new AbstractMap.SimpleEntry<>("valueA", "valueB");
}

private static void usingAbstractMapSimpleResultTest() {
    AbstractMap.SimpleEntry<String, String> result = methodWithAbstractMapSimpleEntryResult();
    System.out.println();
    System.out.println("A = " + result.getKey());
    System.out.println("B = " + result.getValue());
}

6) Usando o Par de Apache Commons

private static Pair<String, String> methodWithPairResult() {
    //...
    return new ImmutablePair<>("valueA", "valueB");
}

private static void usingPairResultTest() {
    Pair<String, String> result = methodWithPairResult();
    System.out.println();
    System.out.println("A = " + result.getKey());
    System.out.println("B = " + result.getValue());
}

16

Quase sempre acabo definindo classes n-Tuple quando codifico em Java. Por exemplo:

public class Tuple2<T1,T2> {
  private T1 f1;
  private T2 f2;
  public Tuple2(T1 f1, T2 f2) {
    this.f1 = f1; this.f2 = f2;
  }
  public T1 getF1() {return f1;}
  public T2 getF2() {return f2;}
}

Eu sei que é um pouco feio, mas funciona, e você só precisa definir seus tipos de tupla uma vez. Tuplas são algo que realmente falta ao Java.

EDIT: O exemplo de David Hanak é mais elegante, pois evita definir getters e ainda mantém o objeto imutável.


9

Antes do Java 5, eu meio que concordava que a solução Map não é ideal. Isso não forneceria a verificação do tipo de tempo de compilação, o que pode causar problemas em tempo de execução. No entanto, com o Java 5, temos tipos genéricos.

Portanto, seu método pode ficar assim:

public Map<String, MyType> doStuff();

MyType, é claro, o tipo de objeto que você está retornando.

Basicamente, acho que retornar um mapa é a solução certa nesse caso, porque é exatamente isso que você deseja retornar - um mapeamento de uma string para um objeto.


Isso não funcionará se algum dos nomes colidir. Uma lista pode conter duplicatas, mas um mapa não pode (conter chaves duplicadas).
tvanfosson

Claro. Eu estava fazendo suposições com base na pergunta - talvez unduely :)
kipz

Embora sua suposição seja verdadeira nesse caso, estou entrando no domínio da otimização prematura (o que não devo fazer).
Jagmal

6

Como alternativa, nas situações em que desejo retornar várias coisas de um método, algumas vezes utilizarei um mecanismo de retorno de chamada em vez de um contêiner. Isso funciona muito bem em situações em que não posso especificar antecipadamente quantos objetos serão gerados.

Com o seu problema específico, seria algo como isto:

public class ResultsConsumer implements ResultsGenerator.ResultsCallback
{
    public void handleResult( String name, Object value )
    {
        ... 
    }
}

public class ResultsGenerator
{
    public interface ResultsCallback
    {
        void handleResult( String aName, Object aValue );
    }

    public void generateResults( ResultsGenerator.ResultsCallback aCallback )
    {
        Object value = null;
        String name = null;

        ...

        aCallback.handleResult( name, value );
    }
}

desculpe-me por comentar uma resposta muito antiga sua, mas como são os retornos de chamada em relação à coleta de lixo? Certamente não compreendo bem o gerenciamento de memória java, se você tiver um objeto Achamado objeto B.getResult()e B.getResult()chama A.finishResult()como a callback, o objeto Bé coletado como lixo ou fica por lá até que A termine? provavelmente uma pergunta estúpida, mas é uma confusão fundamental que eu tenho!
usar o seguinte comando

6

O Apache Commons possui tupla e tripla para isso:

  • ImmutablePair<L,R> Um par imutável que consiste em dois elementos Objeto.
  • ImmutableTriple<L,M,R> Um triplo imutável que consiste em três elementos Objeto.
  • MutablePair<L,R> Um par mutável que consiste em dois elementos Objeto.
  • MutableTriple<L,M,R> Um triplo mutável que consiste em três elementos Objeto.
  • Pair<L,R> Um par que consiste em dois elementos.
  • Triple<L,M,R> Um triplo composto por três elementos.

Fonte: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html


6

Enquanto no seu caso, o comentário pode ser um bom caminho, no Android, você pode usar Pair . Simplesmente

return new Pair<>(yourList, yourCommaSeparatedValues);

5

Uso do seguinte objeto de Entrada Exemplo:

public Entry<A,B> methodname(arg)
{
.......

return new AbstractMap.simpleEntry<A,B>(instanceOfA,instanceOfB);
}

5

Em relação à questão sobre vários valores de retorno em geral, geralmente uso uma classe auxiliar pequena que agrupa um único valor de retorno e é passada como parâmetro para o método:

public class ReturnParameter<T> {
    private T value;

    public ReturnParameter() { this.value = null; }
    public ReturnParameter(T initialValue) { this.value = initialValue; }

    public void set(T value) { this.value = value; }
    public T get() { return this.value; }
}

(para tipos de dados primitivos, utilizo pequenas variações para armazenar diretamente o valor)

Um método que deseja retornar vários valores seria declarado da seguinte maneira:

public void methodThatReturnsTwoValues(ReturnParameter<ClassA> nameForFirstValueToReturn, ReturnParameter<ClassB> nameForSecondValueToReturn) {
    //...
    nameForFirstValueToReturn.set("...");
    nameForSecondValueToReturn.set("...");
    //...
}

Talvez a principal desvantagem seja que o chamador precisa preparar os objetos de retorno antecipadamente, caso queira usá-los (e o método deve verificar se há indicadores nulos)

ReturnParameter<ClassA> nameForFirstValue = new ReturnParameter<ClassA>();
ReturnParameter<ClassB> nameForSecondValue = new ReturnParameter<ClassB>();
methodThatReturnsTwoValues(nameForFirstValue, nameForSecondValue);

Vantagens (em comparação com outras soluções propostas):

  • Você não precisa criar uma declaração de classe especial para métodos individuais e seus tipos de retorno
  • Os parâmetros recebem um nome e, portanto, são mais fáceis de diferenciar ao olhar para a assinatura do método
  • Digite segurança para cada parâmetro

Obrigado por uma solução que fornece nomes e segurança de tipo para cada valor retornado, sem exigir uma declaração de classe por conjunto de tipos de valor retornado.
Home

3

Todas as soluções possíveis serão um kludge (como objetos de contêiner, sua ideia do HashMap, "múltiplos valores de retorno", conforme realizado por meio de matrizes). Eu recomendo regenerar a lista separada por vírgulas da lista retornada. O código acabará sendo muito mais limpo.


Concordo com você, mas, se o fizer, acabarei fazendo um loop duas vezes (na verdade, estou criando os elementos da lista um por um no método existente).
Jagmal

1
@ Jagmal: você pode repetir duas vezes, mas isso não importa na maioria das vezes (consulte a resposta dos aparelhos).
Joachim Sauer

1
Sim, não tente otimizar seu código, a menos que você realmente precise. gizmo está muito certo sobre isso.
Bombe

3

Mantenha-o simples e crie uma classe para situações com vários resultados. Este exemplo aceita um ArrayList e um texto de mensagem de um databasehelper getInfo.

Onde você chama a rotina que retorna vários valores que você codifica:

multResult res = mydb.getInfo(); 

Na rotina getInfo, você codifica:

ArrayList<String> list= new ArrayList<String>();
add values to the list...
return new multResult("the message", list);

e defina uma classe multResult com:

public class multResult {
    public String message; // or create a getter if you don't like public
    public ArrayList<String> list;
    multResult(String m, ArrayList<String> l){
        message = m;
        list= l;
}

}


2

A meu ver, existem realmente três opções aqui e a solução depende do contexto. Você pode optar por implementar a construção do nome no método que produz a lista. Essa é a escolha que você escolheu, mas não acho que seja a melhor. Você está criando um acoplamento no método produtor ao método de consumo que não precisa existir. Outros chamadores podem não precisar de informações adicionais e você calcularia informações adicionais para esses chamadores.

Como alternativa, você pode fazer com que o método de chamada calcule o nome. Se houver apenas um chamador que precise dessas informações, você poderá parar por aí. Você não tem dependências extras e, embora exista um pouco de cálculo extra, evitou tornar seu método de construção muito específico. Este é um bom compromisso.

Por fim, a própria lista pode ser responsável por criar o nome. Esta é a rota que eu seguiria se o cálculo precisasse ser feito por mais de um chamador. Eu acho que isso coloca a responsabilidade pela criação dos nomes com a classe que está mais intimamente relacionada aos próprios objetos.

No último caso, minha solução seria criar uma classe List especializada que retorne uma string separada por vírgula dos nomes dos objetos que ela contém. Torne a classe inteligente o suficiente para que ela construa a string de nome rapidamente, à medida que objetos são adicionados e removidos dela. Em seguida, retorne uma instância desta lista e chame o método de geração de nomes conforme necessário. Embora possa ser quase tão eficiente (e mais simples) simplesmente atrasar o cálculo dos nomes até a primeira vez que o método é chamado e armazená-lo (carregamento lento). Se você adicionar / remover um objeto, precisará remover apenas o valor calculado e recalculá-lo na próxima chamada.


2

Pode fazer algo como uma tupla em linguagem dinâmica (Python)

public class Tuple {
private Object[] multiReturns;

private Tuple(Object... multiReturns) {
    this.multiReturns = multiReturns;
}

public static Tuple _t(Object... multiReturns){
    return new Tuple(multiReturns);
}

public <T> T at(int index, Class<T> someClass) {
    return someClass.cast(multiReturns[index]);
}
}

e use assim

public Tuple returnMultiValues(){
   return Tuple._t(new ArrayList(),new HashMap())
}


Tuple t = returnMultiValues();
ArrayList list = t.at(0,ArrayList.class);

2

Eu segui uma abordagem semelhante à descrita nas outras respostas com alguns ajustes com base no requisito que eu tinha, basicamente criei as seguintes classes (apenas no caso, tudo é Java):

public class Pair<L, R> {
    final L left;
    final R right;

    public Pair(L left, R right) {
        this.left = left;
        this.right = right;
    }

    public <T> T get(Class<T> param) {
        return (T) (param == this.left.getClass() ? this.left : this.right);
    }

    public static <L, R> Pair<L, R> of(L left, R right) {
        return new Pair<L, R>(left, right);
    }
}

Então, meu requisito era simples, na classe do repositório que alcança o banco de dados, para os métodos Get que recuperam dados do banco de dados, preciso verificar se ele falhou ou teve êxito, se tiver êxito, eu precisava brincar com a lista de retorno , se falhar, pare a execução e notifique o erro.

Então, por exemplo, meus métodos são assim:

public Pair<ResultMessage, List<Customer>> getCustomers() {
    List<Customer> list = new ArrayList<Customer>();
    try {
    /*
    * Do some work to get the list of Customers from the DB
    * */
    } catch (SQLException e) {
        return Pair.of(
                       new ResultMessage(e.getErrorCode(), e.getMessage()), // Left 
                       null);  // Right
    }
    return Pair.of(
                   new ResultMessage(0, "SUCCESS"), // Left 
                   list); // Right
}

Onde ResultMessage é apenas uma classe com dois campos (código / mensagem) e Customer é qualquer classe com vários campos provenientes do banco de dados.

Então, para verificar o resultado, basta fazer o seguinte:

void doSomething(){
    Pair<ResultMessage, List<Customer>> customerResult = _repository.getCustomers();
    if (customerResult.get(ResultMessage.class).getCode() == 0) {
        List<Customer> listOfCustomers = customerResult.get(List.class);
        System.out.println("do SOMETHING with the list ;) ");
    }else {
        System.out.println("Raised Error... do nothing!");
    }
}

1

No C ++ (STL), há uma classe de pares para agrupar dois objetos. Em Java Generics, uma classe de pares não está disponível, embora exista alguma demanda por ela. Você pode facilmente implementá-lo você mesmo.

No entanto, concordo com algumas outras respostas: se você precisar retornar dois ou mais objetos de um método, seria melhor encapsulá-los em uma classe.


1

Por que não criar um WhateverFunctionResultobjeto que contenha seus resultados e a lógica necessária para analisá-los, iterar nesse momento etc. Parece-me que:

  1. Esses objetos de resultados estão intimamente ligados / relacionados e pertencem um ao outro, ou:
  2. eles não são relacionados; nesse caso, sua função não está bem definida em termos do que está tentando fazer (por exemplo, fazer duas coisas diferentes)

Vejo esse tipo de problema surgir várias vezes. Não tenha medo de criar suas próprias classes de contêiner / resultado que contêm os dados e a funcionalidade associada para lidar com isso. Se você simplesmente distribuir o material em um HashMapou similar, seus clientes terão que separar esse mapa e separar o conteúdo toda vez que quiserem usar os resultados.


Como é uma PITA ter que definir uma classe sempre que você precisar retornar vários valores, apenas porque o idioma não possui esse recurso geralmente útil;) Mas, falando sério, o que você sugere geralmente vale a pena fazer.
Home

1
public class MultipleReturnValues {

    public MultipleReturnValues() {
    }

    public static void functionWithSeveralReturnValues(final String[] returnValues) {
        returnValues[0] = "return value 1";
        returnValues[1] = "return value 2";
    }

    public static void main(String[] args) {
        String[] returnValues = new String[2];
        functionWithSeveralReturnValues(returnValues);
        System.out.println("returnValues[0] = " + returnValues[0]);
        System.out.println("returnValues[1] = " + returnValues[1]);
    }

}

1

Isso não está respondendo exatamente à pergunta, mas como todas as soluções fornecidas aqui têm algumas desvantagens, sugiro tentar refatorar seu código um pouco para que você precise retornar apenas um valor.

Caso um.

Você precisa de algo dentro e fora do seu método. Por que não calculá-lo fora e passá-lo para o método?

Ao invés de:

[thingA, thingB] = createThings(...);  // just a conceptual syntax of method returning two values, not valid in Java

Experimentar:

thingA = createThingA(...);
thingB = createThingB(thingA, ...);

Isso deve cobrir a maioria das suas necessidades, pois na maioria das situações um valor é criado antes do outro e você pode dividir a criação em dois métodos. A desvantagem é que o método createThingsBpossui um parâmetro extra em comparação com createThings, e possivelmente você está passando exatamente a mesma lista de parâmetros duas vezes para métodos diferentes.


Caso dois.

Solução mais óbvia de todos os tempos e uma versão simplificada do caso um. Nem sempre é possível, mas talvez os dois valores possam ser criados independentemente um do outro?

Ao invés de:

[thingA, thingB] = createThings(...);  // see above

Experimentar:

thingA = createThingA(...);
thingB = createThingB(...);

Para torná-lo mais útil, esses dois métodos podem compartilhar uma lógica comum:

public ThingA createThingA(...) {
    doCommonThings(); // common logic
    // create thing A
}
public ThingB createThingB(...) {
    doCommonThings(); // common logic
    // create thing B
}

0

Passe uma lista para o seu método e preencha-a, depois retorne a String com os nomes, assim:

public String buildList(List<?> list) {
    list.add(1);
    list.add(2);
    list.add(3);
    return "something,something,something,dark side";
}

Então chame assim:

List<?> values = new ArrayList<?>();
String names = buildList(values);

-2

Eu tenho usado uma abordagem muito básica para lidar com problemas de retornos múltiplos. Ele serve ao propósito e evita a complexidade.

Eu chamo-lhe a corda separador Approach

E é eficaz, pois pode até retornar valores de Vários Tipos, por exemplo, int, double, char, string etc.

Nesta abordagem, usamos uma string que é muito improvável que ocorra geralmente. Chamamos isso de separador. Esse separador seria usado para separar vários valores quando usado em uma função

Por exemplo, teremos nosso retorno final como (por exemplo) separador intValue separador doubleValue ... E, usando essa string, recuperaremos todas as informações necessárias, que também podem ser de tipos diferentes

O código a seguir mostrará o funcionamento desse conceito

O separador usado é ! @ # E 3 valores estão sendo retornados intVal, doubleVal e stringVal

        public class TestMultipleReturns {

            public static String multipleVals() {

                String result = "";
                String separator = "!@#";


                int intVal = 5;
                // Code to process intVal

                double doubleVal = 3.14;
                // Code to process doubleVal

                String stringVal = "hello";
                // Code to process Int intVal

                result = intVal + separator + doubleVal + separator + stringVal + separator;
                return (result);
            }

            public static void main(String[] args) {

                String res = multipleVals();

                int intVal = Integer.parseInt(res.split("!@#")[0]);
                // Code to process intVal

                double doubleVal = Double.parseDouble(res.split("!@#")[1]);
                // Code to process doubleVal

                String stringVal = res.split("!@#")[2];

                System.out.println(intVal+"\n"+doubleVal+"\n"+stringVal);
            }
        }

RESULTADO

5
3.14
hello
BUILD SUCCESSFUL (total time: 2 seconds)

3
yuk. Cheiro de código enorme. Análise, em vez de usar os recursos Orientados a Objetos disponíveis. IMO, um dos piores exemplos de codificação que eu já vi. A menos que você esteja descrevendo uma situação em que precise passar vários valores entre dois programas independentes ou outra comunicação entre processos e, de alguma forma, não tenha acesso a um mecanismo decente para fazê-lo (json ou outro).
Home

-4

Em C, você faria isso passando ponteiros para espaços reservados para os resultados como argumentos:

void getShoeAndWaistSizes(int *shoeSize, int *waistSize) {
    *shoeSize = 36;
    *waistSize = 45;
}
...
int shoeSize, waistSize;
getShoeAndWaistSize(&shoeSize, &waistSize);
int i = shoeSize + waistSize;

Vamos tentar algo semelhante, em Java.

void getShoeAndWaistSizes(List<Integer> shoeSize, List<Integer> waistSize) {
    shoeSize.add(36);
    waistSize.add(45);
}
...
List<Integer> shoeSize = new List<>();
List<Integer> waistSize = new List<>();
getShoeAndWaistSizes(shoeSize, waistSize);
int i = shoeSize.get(0) + waistSize.get(0);

1
No entanto, em uma linguagem OO, geralmente é considerado preferível fazer o que várias pessoas já sugeriram quatro anos antes desta resposta: agrupar os dois valores relacionados em um objeto (par, tupla ou definição de classe personalizada) e, em seguida, ter uma lista desses objetos. Isso evita a necessidade de distribuir várias listas. Isso se torna especialmente importante se for necessário passar esse par (um elemento de cada uma de suas listas) para outros métodos, para processamento adicional.
Home

@ToolmakerSteve Para esclarecer: as listas destinam-se a ter exatamente um elemento cada e são apenas um meio de implementar um analógico para passar por ponteiro. Eles não têm a intenção de coletar vários resultados ou mesmo serem usados ​​além de algumas linhas após a chamada do método.
Adrian Panasiuk

-5

PASSE UM HASH PARA O MÉTODO E POPULUE-O ......

public void buildResponse (dados da string, resposta do mapa);

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.