Converting lists of one element type to a list of another type
I’m writing an adapter framework where I need to convert a list of objects from one class to another. I can iterate through the source list to do this as in Java: Best way of converting List to List However, I’m wondering if there is a way to do this on the fly when the target list is being iterated, so I don’t have to iterate through the list twice.
12 Answers 12
List original = . ; List converted = original.stream().map(Wrapper::new).collect(Collectors.toList());
assuming Wrapper class has a constructor accepting a String .
My answer to that question applies to your case:
import com.google.common.collect.Lists; import com.google.common.base.Functions List integers = Arrays.asList(1, 2, 3, 4); List strings = Lists.transform(integers, Functions.toStringFunction());
The transformed list is a view on the original collection, so the transformation happens when the destination List is accessed.
As an alternative to the iterator pattern, you can use a abstract generic mapper class, and only override the transform method:
- create a generic collection mapper for any data type
- [optional] create a library of methods that transform between different data types (and override the method)
- use that library
// Generic class to transform collections public abstract class CollectionTransformer < abstract F transform(E e); public Listtransform(List list) < ListnewList = new ArrayList(); for (E e : list) < newList.add(transform(e)); >return newList; > > // Method that transform Integer to String // this override the transform method to specify the transformation public static List mapIntegerToStringCollection(List list) < CollectionTransformer transformer = new CollectionTransformer() < @Override String transform(Integer e) < return e.toString(); >>; return transformer.transform(list); > // Example Usage List integers = Arrays.asList(1,2); List strings = mapIntegerToStringCollection(integers);
This would be useful is you have to use transformations every time, encapsulating the process. So you can make a library of collection mappers very easy.
Создать ArrayList с несколькими типами объектов?
это будет типа String . Как я могу создать ArrayList который может принимать как целочисленные, так и строковые типы ввода? Спасибо.
11 ответов
Пример списка классов массивов, определенных пользователем
import java.util.*; public class UserDefinedClassInArrayList < public static void main(String[] args) < //Creating user defined class objects Student s1=new Student(1,"AAA",13); Student s2=new Student(2,"BBB",14); Student s3=new Student(3,"CCC",15); ArrayListal=new ArrayList(); al.add(s1); al.add(s2); al.add(s3); Iterator itr=al.iterator(); //traverse elements of ArrayList object while(itr.hasNext()) < Student st=(Student)itr.next(); System.out.println(st.rollno+" "+st.name+" "+st.age); >> > class Student < int rollno; String name; int age; Student(int rollno,String name,int age)< this.rollno=rollno; this.name=name; this.age=age; >>
Выход программы:
Почему это решение было принято, когда оно не отвечает на вопрос о массиве нескольких типов объектов. Все, что вы здесь сделали, — это один и тот же тип объекта ArrayList
Вы можете сделать это как:
List sections = new ArrayList ();
(Рекомендуемый) Еще одним возможным решением могло бы стать создание пользовательского класса модели с двумя параметрами: одним целым и другой строкой. Затем используйте ArrayList этого объекта.
Да, на мой взгляд, «создать пользовательский класс модели с двумя параметрами» равен классу-оболочке с 2 конструкторами. Таким образом, вы можете определить новый список класса-оболочки типа: List
@735Tesla..735Tesla .. Создание собственного модельного класса является предпочтительным способом. Вы можете включить ваши примитивные типы данных в один и использовать список класса модели.
Когда не используются конечные классы или примитивы, я предпочитаю создавать интерфейс, описывающий то, что я собираюсь делать с коллекцией, и реализовывать этот интерфейс (который может иметь только метод toString () или вообще не иметь методов) в оригинальный класс или класс-оболочка и использовать этот интерфейс в качестве типа коллекции. Я считаю, что это будет намного чище для будущих сопровождающих, которые могут быстро понять, почему ваша универсальная коллекция имеет несколько типов, как она предназначена для потребления, и как добавить больше типов, если это когда-либо понадобится (что даже не потребует изменения коллекция).
Вы также можете просто использовать List section = new ArrayList (); Поведение arraylist по умолчанию перед универсальными шаблонами заключалось в том, чтобы принимать любые объекты и оставлять приведение на усмотрение клиента.
Вы можете использовать Object для хранения любого типа значения, например. int, float, String, объекты класса или любые другие java-объекты, поскольку это корень всего класса. Например,
class Person < public int personId; public String personName; public int getPersonId() < return personId; >public void setPersonId(int personId) < this.personId = personId; >public String getPersonName() < return personName; >public void setPersonName(String personName) < this.personName = personName; >>
Person p = new Person(); p.setPersonId(1); p.setPersonName("Tom"); List lstObject = new ArrayList(); lstObject.add(1232); lstObject.add("String"); lstObject.add(122.212f); lstObject.add(p); for (Object obj : lstObject) < if (obj.getClass() == String.class) < System.out.println("I found a string :- " + obj); >if (obj.getClass() == Integer.class) < System.out.println("I found an int :- " + obj); >if (obj.getClass() == Float.class) < System.out.println("I found a float :- " + obj); >if (obj.getClass() == Person.class) < Person person = (Person) obj; System.out.println("I found a person object"); System.out.println("Person Id :- " + person.getPersonId()); System.out.println("Person Name :- " + person.getPersonName()); >>
Более подробную информацию о классе объектов можно найти по этой ссылке Объект в java
Это хороший пример ужасного запаха кода. Никогда не следует использовать ArrayList объектов. Обычно лучше использовать редизайн кода, чем использовать getClass / instanceof и downcasts для использования ArrayList.
Мне придется понизить голос, вам не следует использовать: .class или получать ArrayList of Object (в основном ArrayList всего).
Искренне ищу лучшее решение: как отсортировать различные классы объектов по общему свойству, не создавая ArrayList родительского класса или интерфейса и не используя getClass() или instanceof для сравнения — есть ли лучший способ?
ArrayList list = new ArrayList <>();' list.add("ddd"); list.add(2); list.add(11122.33); System.out.println(list);
ArrayList arraylist = new ArrayList(); arraylist.add(5); arraylist.add("saman"); arraylist.add(4.3); System.out.println(arraylist);
Я также новичок в Java и просто понял это. Вы должны создать свой собственный класс, который хранит строку и целое число, а затем составить список этих объектов. Например (я уверен, что этот код несовершенен, но лучше, чем arrayList):
class Stuff < private String label; private Integer value; // Constructor or setter public void Stuff(String label, Integer value) < if (label == null || value == null) < return; >this.label = label; this.value = value; > // getters public String getLabel() < return this.label; >public Integer getValue() < return this.value; >>
private ArrayList items = new ArrayList(); items.add(new Stuff(label, value)); for (Stuff item: items) < doSomething(item.getLabel()); // returns String doSomething(item.getValue()); // returns Integer >
Вы не знаете, что тип Integer или String вам не нужен. Пойдите со старым стилем.
List list= new ArrayList (); list.add(1); list.add("myname"); for(Object o = list)
Да, измените дизайн программы, чтобы вам не приходилось собирать апельсины с орангутангами. Исходный вопрос имеет сильный запах кода, который кричит (по крайней мере, мне), что дизайн отключен, если он требует такой конструкции.
Это зависит от варианта использования. Не могли бы вы описать это больше?
- Если вы хотите иметь возможность добавлять оба за один раз, чем вы можете сделать, что хорошо описано @Sanket Parikh. Поместите Integer и String в новый класс и используйте это.
- Если вы хотите добавить список либо String, либо int, но только один из них за раз, тогда убедитесь, что это List который выглядит хорошо, но только для первого взгляда! Это не очень хорошая модель. Вам нужно будет проверить, какой тип объекта у вас есть каждый раз, когда вы получаете объект из своего списка. Также этот тип списка может содержать любые другие типы. Так что нет, это не хорошее решение. Хотя, возможно, для новичков он может быть использован. Если вы выберете это, я бы рекомендовал проверить, что такое «instanceof» в Java.
- Я бы настоятельно рекомендовал пересмотреть ваши потребности и подумать о том, может быть, ваш настоящий nead должен инкапсулировать целые числа в List и строки в отдельный List
Могу ли я рассказать вам метафору о том, что вы хотите сделать сейчас? Я бы сказал, что вы хотите составить список, который может содержать кофе beans и кафе. Эти типы объектов совершенно разные! Почему они помещаются на одну полку?:)
Или у вас есть данные, которые могут быть словом или числом? Yepp! Это будет иметь смысл, оба они являются данными! Затем попробуйте использовать один объект для того, который содержит данные как String, и при необходимости может быть переведен на целочисленное значение.
public class MyDataObj < String info; boolean isNumeric; public MyDataObj(String info)< setInfo(info); >public MyDataObj(Integer info) < setInfo(info); >public String getInfo() < return info; >public void setInfo(String info) < this.info = info; this.isNumeric = false; >public void setInfo(Integer info) < this.info = Integer.toString(info); this.isNumeric = true; >public boolean isNumeric() < return isNumeric; >>
Таким образом, вы можете использовать List для своих нужд. Опять же, это зависит от ваших потребностей!:)
Некоторое издание: как насчет использования вдыхания? Это лучше тогда решение List , потому что вы не можете иметь другие типы в списке, затем строки или целые числа: Интерфейс:
public interface IMyDataObj
public class MyStringDataObj implements IMyDataObj < final String info; public MyStringDataObj(String info)< this.info = info; >@Override public String getInfo() < return info; >>
public class MyIntegerDataObj implements IMyDataObj < final Integer info; public MyIntegerDataObj(Integer info) < this.info = info; >@Override public String getInfo() < return Integer.toString(info); >>
Наконец, список будет выглядеть следующим образом: List
Interface List
An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted. The user can access elements by their integer index (position in the list), and search for elements in the list.
Unlike sets, lists typically allow duplicate elements. More formally, lists typically allow pairs of elements e1 and e2 such that e1.equals(e2) , and they typically allow multiple null elements if they allow null elements at all. It is not inconceivable that someone might wish to implement a list that prohibits duplicates, by throwing runtime exceptions when the user attempts to insert them, but we expect this usage to be rare.
The List interface places additional stipulations, beyond those specified in the Collection interface, on the contracts of the iterator , add , remove , equals , and hashCode methods. Declarations for other inherited methods are also included here for convenience.
The List interface provides four methods for positional (indexed) access to list elements. Lists (like Java arrays) are zero based. Note that these operations may execute in time proportional to the index value for some implementations (the LinkedList class, for example). Thus, iterating over the elements in a list is typically preferable to indexing through it if the caller does not know the implementation.
The List interface provides a special iterator, called a ListIterator , that allows element insertion and replacement, and bidirectional access in addition to the normal operations that the Iterator interface provides. A method is provided to obtain a list iterator that starts at a specified position in the list.
The List interface provides two methods to search for a specified object. From a performance standpoint, these methods should be used with caution. In many implementations they will perform costly linear searches.
The List interface provides two methods to efficiently insert and remove multiple elements at an arbitrary point in the list.
Note: While it is permissible for lists to contain themselves as elements, extreme caution is advised: the equals and hashCode methods are no longer well defined on such a list.
Some list implementations have restrictions on the elements that they may contain. For example, some implementations prohibit null elements, and some have restrictions on the types of their elements. Attempting to add an ineligible element throws an unchecked exception, typically NullPointerException or ClassCastException . Attempting to query the presence of an ineligible element may throw an exception, or it may simply return false; some implementations will exhibit the former behavior and some will exhibit the latter. More generally, attempting an operation on an ineligible element whose completion would not result in the insertion of an ineligible element into the list may throw an exception or it may succeed, at the option of the implementation. Such exceptions are marked as «optional» in the specification for this interface.
Unmodifiable Lists
- They are unmodifiable. Elements cannot be added, removed, or replaced. Calling any mutator method on the List will always cause UnsupportedOperationException to be thrown. However, if the contained elements are themselves mutable, this may cause the List’s contents to appear to change.
- They disallow null elements. Attempts to create them with null elements result in NullPointerException .
- They are serializable if all elements are serializable.
- The order of elements in the list is the same as the order of the provided arguments, or of the elements in the provided array.
- The lists and their subList views implement the RandomAccess interface.
- They are value-based. Programmers should treat instances that are equal as interchangeable and should not use them for synchronization, or unpredictable behavior may occur. For example, in a future release, synchronization may fail. Callers should make no assumptions about the identity of the returned instances. Factories are free to create new instances or reuse existing ones.
- They are serialized as specified on the Serialized Form page.
This interface is a member of the Java Collections Framework.