Flattening a collection

前端 未结 9 2011
走了就别回头了
走了就别回头了 2020-11-30 02:55

Say I have a Map>

I can get the values of the map easily enough, and iterate over it to produce a single

相关标签:
9条回答
  • 2020-11-30 03:14

    When searching for "java 8 flatten" this is the only mentioning. And it's not about flattening stream either. So for great good I just leave it here

    .flatMap(Collection::stream)
    

    I'm also surprised no one has given concurrent java 8 answer to original question which is

    .collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);
    
    0 讨论(0)
  • 2020-11-30 03:17

    Flatten on a function:

        private <A, T> List<T> flatten(List<A> list, Function<A, List<T>> flattenFn) {
            return list
                    .stream()
                    .map(flattenFn)
                    .flatMap(Collection::stream)
                    .collect(Collectors.toUnmodifiableList());
        }
    
    0 讨论(0)
  • 2020-11-30 03:19

    If you are using Java 8, you could do something like this:

    someMap.values().forEach(someList::addAll);
    
    0 讨论(0)
  • 2020-11-30 03:24

    If you just want to iterate through values, you can avoid all these addAll methods.

    All you have to do is write a class that encapsulates your Map, and that implements the Iterator :

    public class ListMap<K,V> implements Iterator<V>
    {
      private final Map<K,List<V>> _map;
      private Iterator<Map.Entry<K,List<V>>> _it1 = null;
      private Iterator<V> _it2 = null;
    
      public ListMap(Map<K,List<V>> map)
      {
        _map = map;
        _it1 = map.entrySet().iterator(); 
        nextList();
      }
    
      public boolean hasNext()
      {
        return _it2!=null && _it2.hasNext();
      }
    
      public V next()
      {
        if(_it2!=null && _it2.hasNext())
        {
          return _it2.next();
        }
        else
        {
          throw new NoSuchElementException();
        }
        nextList();
      } 
    
      public void remove()
      {
        throw new NotImplementedException();
      }
    
      private void nextList()
      {
        while(_it1.hasNext() && !_it2.hasNext())
        {
          _it2 = _it1.next().value();
        }
      }
    }
    
    0 讨论(0)
  • 2020-11-30 03:25

    A nice solution for the subcase of a Map of Maps is to store, if possible, the data in Guava's Table.

    https://github.com/google/guava/wiki/NewCollectionTypesExplained#table

    So for instance a Map<String,Map<String,String>> is replaced by Table<String,String,String> which is already flattend. In fact, the docs say that HashBasedTable, Table's Hash implementation, is essentially backed by a HashMap<R, HashMap<C, V>>

    0 讨论(0)
  • If you're using Eclipse Collections, you can use Iterate.flatten().

    MutableMap<String, MutableList<String>> map = Maps.mutable.empty();
    map.put("Even", Lists.mutable.with("0", "2", "4"));
    map.put("Odd", Lists.mutable.with("1", "3", "5"));
    MutableList<String> flattened = Iterate.flatten(map, Lists.mutable.empty());
    Assert.assertEquals(
        Lists.immutable.with("0", "1", "2", "3", "4", "5"),
        flattened.toSortedList());
    

    flatten() is a special case of the more general RichIterable.flatCollect().

    MutableList<String> flattened = 
        map.flatCollect(x -> x, Lists.mutable.empty());
    

    Note: I am a committer for Eclipse Collections.

    0 讨论(0)
提交回复
热议问题